]> git.kaiwu.me - njs.git/commitdiff
Improved backtrace reporting for stack overflow.
authorDmitry Volyntsev <xeioex@nginx.com>
Thu, 22 Nov 2018 12:35:25 +0000 (15:35 +0300)
committerDmitry Volyntsev <xeioex@nginx.com>
Thu, 22 Nov 2018 12:35:25 +0000 (15:35 +0300)
njs/njs_vm.c
njs/test/njs_interactive_test.c

index cdf80a5dc06e6125ac2ae3c5b9bf3c2d6ff40265..819271d40f269a8efe342dbd62a76ff954bcdc70 100644 (file)
@@ -3202,12 +3202,12 @@ njs_vm_value_to_ext_string(njs_vm_t *vm, nxt_str_t *dst, const njs_value_t *src,
     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;
index e83c08c35c2a262c5f2cad0e2f63ef6c77d81b49..d4c2d13d6bc08627668bddade25f1ea973c16928 100644 (file)
@@ -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