[njs] Improved backtrace reporting for stack overflow.

Dmitry Volyntsev xeioex at nginx.com
Thu Nov 22 12:54:42 UTC 2018


details:   https://hg.nginx.org/njs/rev/987f7998a967
branches:  
changeset: 663:987f7998a967
user:      Dmitry Volyntsev <xeioex at nginx.com>
date:      Thu Nov 22 15:35:25 2018 +0300
description:
Improved backtrace reporting for stack overflow.

diffstat:

 njs/njs_vm.c                    |  63 ++++++++++++++++++++++++++++++++--------
 njs/test/njs_interactive_test.c |   6 +++
 2 files changed, 56 insertions(+), 13 deletions(-)

diffs (117 lines):

diff -r 01f2cbf5acc4 -r 987f7998a967 njs/njs_vm.c
--- a/njs/njs_vm.c	Thu Nov 22 15:02:19 2018 +0300
+++ b/njs/njs_vm.c	Thu Nov 22 15:35:25 2018 +0300
@@ -3202,12 +3202,12 @@ njs_vm_value_to_ext_string(njs_vm_t *vm,
     nxt_uint_t handle_exception)
 {
     u_char                 *p, *start;
-    size_t                 len, size;
+    size_t                 len, size, count;
     njs_ret_t              ret;
     nxt_uint_t             i, exception;
     nxt_array_t            *backtrace;
     njs_value_t            value;
-    njs_backtrace_entry_t  *be;
+    njs_backtrace_entry_t  *be, *prev;
 
     exception = handle_exception;
 
@@ -3273,17 +3273,35 @@ again:
 
                 len = dst->length + 1;
 
+                count = 0;
+                prev = NULL;
+
                 be = backtrace->start;
 
                 for (i = 0; i < backtrace->items; i++) {
-                    if (be[i].line != 0) {
-                        len += sizeof("    at  (:)\n") + 10
-                               + be[i].name.length;
+                    if (i != 0 && prev->name.start == be[i].name.start
+                        && prev->line == be[i].line)
+                    {
+                        count++;
 
                     } else {
-                        len += sizeof("    at  (native)\n")
-                               + be[i].name.length;
+
+                        if (count != 0) {
+                            len += sizeof("      repeats  times\n") + 10;
+                            count = 0;
+                        }
+
+                        if (be[i].line != 0) {
+                            len += sizeof("    at  (:)\n") + 10
+                                   + be[i].name.length;
+
+                        } else {
+                            len += sizeof("    at  (native)\n")
+                                   + be[i].name.length;
+                        }
                     }
+
+                    prev = &be[i];
                 }
 
                 p = nxt_mem_cache_alloc(vm->mem_cache_pool, len);
@@ -3297,16 +3315,35 @@ again:
                 p = nxt_cpymem(p, dst->start, dst->length);
                 *p++ = '\n';
 
+                count = 0;
+                prev = NULL;
+
                 for (i = 0; i < backtrace->items; i++) {
-                    if (be[i].line != 0) {
-                        p += sprintf((char *) p, "    at %.*s (:%u)\n",
-                                     (int) be[i].name.length, be[i].name.start,
-                                     be[i].line);
+                    if (i != 0 && prev->name.start == be[i].name.start
+                        && prev->line == be[i].line)
+                    {
+                        count++;
 
                     } else {
-                        p += sprintf((char *) p, "    at %.*s (native)\n",
-                                     (int) be[i].name.length, be[i].name.start);
+                        if (count != 0) {
+                            p += sprintf((char *) p,
+                                         "      repeats %zu times\n", count);
+                            count =0;
+                        }
+
+                        if (be[i].line != 0) {
+                            p += sprintf((char *) p, "    at %.*s (:%u)\n",
+                                         (int) be[i].name.length,
+                                         be[i].name.start, be[i].line);
+
+                        } else {
+                            p += sprintf((char *) p, "    at %.*s (native)\n",
+                                         (int) be[i].name.length,
+                                         be[i].name.start);
+                        }
                     }
+
+                    prev = &be[i];
                 }
 
                 dst->start = start;
diff -r 01f2cbf5acc4 -r 987f7998a967 njs/test/njs_interactive_test.c
--- a/njs/test/njs_interactive_test.c	Thu Nov 22 15:02:19 2018 +0300
+++ b/njs/test/njs_interactive_test.c	Thu Nov 22 15:35:25 2018 +0300
@@ -220,6 +220,12 @@ static njs_interactive_test_t  njs_test[
                  "    at parseInt (native)\n"
                  "    at main (native)\n") },
 
+    { nxt_string("function f(n) { if (n == 0) { throw 'a'; } return f(n-1); }; f(2)" ENTER),
+      nxt_string("a\n"
+                 "    at f (:1)\n"
+                 "      repeats 2 times\n"
+                 "    at main (native)\n") },
+
     /* Exception in njs_vm_retval_to_ext_string() */
 
     { nxt_string("var o = { toString: function() { return [1] } }" ENTER


More information about the nginx-devel mailing list