]> git.kaiwu.me - njs.git/commitdiff
Modules: suppressed slab log_nomem for evict shared dict zones.
authorDmitry Volyntsev <xeioex@nginx.com>
Wed, 25 Feb 2026 07:13:54 +0000 (23:13 -0800)
committerDmitry Volyntsev <xeioexception@gmail.com>
Wed, 25 Feb 2026 20:51:29 +0000 (12:51 -0800)
When evict is enabled, memory allocation failures are expected
and handled by evicting old entries.  The slab allocator's
"no memory" log messages are now suppressed for such zones.

nginx/ngx_js_shared_dict.c
nginx/t/js_shared_dict.t

index 7eb13a700b51e38297d72cb773c862af5658f714..a7273df566f3a2987d29b64db8deb45b09ee0146 100644 (file)
@@ -1302,7 +1302,9 @@ ngx_js_dict_alloc(ngx_js_dict_t *dict, size_t n)
 {
     void  *p;
 
+    dict->shpool->log_nomem = !dict->evict;
     p = ngx_slab_alloc_locked(dict->shpool, n);
+    dict->shpool->log_nomem = 1;
 
     if (p == NULL && dict->evict) {
         ngx_js_dict_evict(dict, 16);
index b27a33ef4ede71b2b1b35145a8dbf3da1c768520..34a2a6421d9f9afc494d3b0b14bae7d7144fa629 100644 (file)
@@ -100,6 +100,10 @@ http {
             js_content test.name;
         }
 
+        location /evict_stress {
+            js_content test.evict_stress;
+        }
+
         location /overflow {
             js_content test.overflow;
         }
@@ -261,6 +265,31 @@ $t->write_file('test.js', <<'EOF');
         r.return(200, dict.replace(r.args.key, value));
     }
 
+    function evict_stress(r) {
+        var dict = ngx.shared.foo;
+        dict.clear();
+
+        var v = 'x'.repeat(1024);
+        var n = 64;
+        var failed = 0;
+
+        for (var i = 0; i < n; i++) {
+            try {
+                dict.set('stress_' + i, v);
+            } catch (e) {
+                failed++;
+            }
+        }
+
+        var last = dict.get('stress_' + (n - 1));
+        var first = dict.get('stress_0');
+
+        var last_s = last !== undefined ? 'exists' : 'missing';
+        var first_s = first !== undefined ? 'exists' : 'missing';
+
+        r.return(200, `failed:${failed},last:${last_s},first:${first_s}`);
+    }
+
     function overflow(r) {
         var dict = ngx.shared.overflow;
 
@@ -327,14 +356,15 @@ $t->write_file('test.js', <<'EOF');
         r.return(200, Object.keys(ngx.shared).sort());
     }
 
-    export default { add, capacity, chain, clear, del, free_space, get, has,
-                     incr, items, keys, name, njs: test_njs, pop, replace, set,
-                     set_clear, size, zones, overflow };
+    export default { add, capacity, chain, clear, del, evict_stress,
+                     free_space, get, has, incr, items, keys, name,
+                     njs: test_njs, pop, replace, set, set_clear, size,
+                     zones, overflow };
 EOF
 
 $t->try_run('no js_shared_dict_zone');
 
-$t->plan(52);
+$t->plan(56);
 
 ###############################################################################
 
@@ -438,6 +468,13 @@ like(http_get('/overflow'), qr/SharedMemoryError/, 'overflow exception');
 
 }
 
+my $evict_resp = http_get('/evict_stress');
+like($evict_resp, qr/failed:0/, 'evict stress: all writes succeeded');
+like($evict_resp, qr/last:exists/, 'evict stress: last write exists');
+like($evict_resp, qr/first:missing/, 'evict stress: first write evicted');
+unlike($t->read_file('error.log'), qr/no memory in js shared zone "foo"/,
+       'evict stress: no shared zone foo errors in error log');
+
 ###############################################################################
 
 sub has_version {