[njs] Fixed tracking of unhandled rejected promises.

Dmitry Volyntsev xeioex at nginx.com
Sat Jan 20 02:16:47 UTC 2024


details:   https://hg.nginx.org/njs/rev/da8b044e1c61
branches:  
changeset: 2268:da8b044e1c61
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Jan 18 18:03:24 2024 -0800
description:
Fixed tracking of unhandled rejected promises.

Checking for unhandled promise rejections while looping for pending jobs
produces false-positive reports when an rejected promised is handled
by one of the pending jobs later.

The fix is to check for unhandled promise rejections only at top level
calls like ngx_js_name_invoke() and ngx_js_name_call() and only after
all pending jobs are processed.

The issue was introduced in bc80bcb3102c (not released yet).

diffstat:

 external/njs_shell.c          |  10 +++++++++-
 nginx/ngx_js.c                |  11 +++++++++--
 src/test/njs_externals_test.c |   2 +-
 src/test/njs_unit_test.c      |   4 +---
 4 files changed, 20 insertions(+), 7 deletions(-)

diffs (88 lines):

diff -r 4fba78789fe4 -r da8b044e1c61 external/njs_shell.c
--- a/external/njs_shell.c	Thu Jan 11 15:13:47 2024 -0800
+++ b/external/njs_shell.c	Thu Jan 18 18:03:24 2024 -0800
@@ -1100,7 +1100,7 @@ njs_process_script(njs_vm_t *vm, void *r
         for ( ;; ) {
             ret = njs_vm_execute_pending_job(vm);
             if (ret <= NJS_OK) {
-                if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) {
+                if (ret == NJS_ERROR) {
                     njs_process_output(vm, NULL, ret);
 
                     if (!njs_vm_options(vm)->interactive) {
@@ -1112,6 +1112,14 @@ njs_process_script(njs_vm_t *vm, void *r
             }
         }
 
+        if (njs_vm_unhandled_rejection(vm)) {
+            njs_process_output(vm, NULL, NJS_ERROR);
+
+            if (!njs_vm_options(vm)->interactive) {
+                return NJS_ERROR;
+            }
+        }
+
         ret = njs_process_events(runtime);
         if (njs_slow_path(ret == NJS_ERROR)) {
             break;
diff -r 4fba78789fe4 -r da8b044e1c61 nginx/ngx_js.c
--- a/nginx/ngx_js.c	Thu Jan 11 15:13:47 2024 -0800
+++ b/nginx/ngx_js.c	Thu Jan 18 18:03:24 2024 -0800
@@ -357,7 +357,7 @@ ngx_js_call(njs_vm_t *vm, njs_function_t
         if (ret <= NJS_OK) {
             c = ngx_external_connection(vm, njs_vm_external_ptr(vm));
 
-            if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) {
+            if (ret == NJS_ERROR) {
                 ngx_js_exception(vm, &exception);
 
                 ngx_log_error(NGX_LOG_ERR, c->log, 0,
@@ -417,7 +417,7 @@ ngx_js_name_invoke(njs_vm_t *vm, ngx_str
     for ( ;; ) {
         ret = njs_vm_execute_pending_job(vm);
         if (ret <= NJS_OK) {
-            if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) {
+            if (ret == NJS_ERROR) {
                 ngx_js_exception(vm, &exception);
 
                 ngx_log_error(NGX_LOG_ERR, log, 0,
@@ -429,6 +429,13 @@ ngx_js_name_invoke(njs_vm_t *vm, ngx_str
         }
     }
 
+    if (njs_vm_unhandled_rejection(vm)) {
+        ngx_js_exception(vm, &exception);
+
+        ngx_log_error(NGX_LOG_ERR, log, 0, "js exception: %V", &exception);
+        return NGX_ERROR;
+    }
+
     ctx = ngx_external_ctx(vm, njs_vm_external_ptr(vm));
 
     return njs_rbtree_is_empty(&ctx->waiting_events) ? NGX_OK : NGX_AGAIN;
diff -r 4fba78789fe4 -r da8b044e1c61 src/test/njs_externals_test.c
--- a/src/test/njs_externals_test.c	Thu Jan 11 15:13:47 2024 -0800
+++ b/src/test/njs_externals_test.c	Thu Jan 18 18:03:24 2024 -0800
@@ -1485,7 +1485,7 @@ njs_external_call(njs_vm_t *vm, const nj
     for ( ;; ) {
         ret = njs_vm_execute_pending_job(vm);
         if (ret <= NJS_OK) {
-            if (ret == NJS_ERROR || njs_vm_unhandled_rejection(vm)) {
+            if (ret == NJS_ERROR) {
                 return NJS_ERROR;
             }
 
diff -r 4fba78789fe4 -r da8b044e1c61 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c	Thu Jan 11 15:13:47 2024 -0800
+++ b/src/test/njs_unit_test.c	Thu Jan 18 18:03:24 2024 -0800
@@ -23708,9 +23708,7 @@ njs_process_test(njs_external_state_t *s
             for ( ;; ) {
                 ret = njs_vm_execute_pending_job(state->vm);
                 if (ret <= NJS_OK) {
-                    if (ret == NJS_ERROR
-                        || njs_vm_unhandled_rejection(state->vm))
-                    {
+                    if (ret == NJS_ERROR) {
                         return NJS_ERROR;
                     }
 


More information about the nginx-devel mailing list