[njs] Stream: fixed CPU hog when js_filter is registered in both directions.

Dmitry Volyntsev xeioex at nginx.com
Thu Aug 12 16:40:00 UTC 2021


details:   https://hg.nginx.org/njs/rev/377743cd9059
branches:  
changeset: 1687:377743cd9059
user:      Miao Wang <shankerwangmiao at gmail.com>
date:      Wed Aug 11 11:44:12 2021 +0800
description:
Stream: fixed CPU hog when js_filter is registered in both directions.

Previously, a single busy chain was used to track filtered data in both
directions.  This might lead to a situation when busy chunks are not
freed properly and pile up.

The fix is to separate busy chain for upstream and downstream directions.

This closes #413 issue on Github.

diffstat:

 nginx/ngx_stream_js_module.c |  9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diffs (41 lines):

diff -r 80adcb502e40 -r 377743cd9059 nginx/ngx_stream_js_module.c
--- a/nginx/ngx_stream_js_module.c	Wed Aug 11 21:48:52 2021 +0300
+++ b/nginx/ngx_stream_js_module.c	Wed Aug 11 11:44:12 2021 +0800
@@ -49,7 +49,8 @@ typedef struct {
     ngx_buf_t              *buf;
     ngx_chain_t           **last_out;
     ngx_chain_t            *free;
-    ngx_chain_t            *busy;
+    ngx_chain_t            *upstream_busy;
+    ngx_chain_t            *downstream_busy;
     ngx_int_t               status;
 #define NGX_JS_EVENT_UPLOAD   0
 #define NGX_JS_EVENT_DOWNLOAD 1
@@ -528,7 +529,7 @@ ngx_stream_js_body_filter(ngx_stream_ses
     njs_str_t                  exception;
     njs_int_t                  ret;
     ngx_int_t                  rc;
-    ngx_chain_t               *out, *cl;
+    ngx_chain_t               *out, *cl, **busy;
     ngx_connection_t          *c, *dst;
     ngx_stream_js_ev_t        *event;
     ngx_stream_js_ctx_t       *ctx;
@@ -606,15 +607,17 @@ ngx_stream_js_body_filter(ngx_stream_ses
 
     if (from_upstream) {
         dst = c;
+        busy = &ctx->downstream_busy;
 
     } else {
         dst = s->upstream ? s->upstream->peer.connection : NULL;
+        busy = &ctx->upstream_busy;
     }
 
     if (out != NULL || dst == NULL || dst->buffered) {
         rc = ngx_stream_next_filter(s, out, from_upstream);
 
-        ngx_chain_update_chains(c->pool, &ctx->free, &ctx->busy, &out,
+        ngx_chain_update_chains(c->pool, &ctx->free, busy, &out,
                                 (ngx_buf_tag_t) &ngx_stream_js_module);
 
     } else {


More information about the nginx-devel mailing list