astmm.c: Display backtrace with memory show allocations
authorGeorge Joseph <gjoseph@digium.com>
Mon, 23 Sep 2019 12:09:29 +0000 (06:09 -0600)
committerGeorge Joseph <gjoseph@digium.com>
Mon, 23 Sep 2019 12:25:33 +0000 (07:25 -0500)
You can currently capture backtraces of memory allocations but they
only get displayed when you stop asterisk and the atexit hooks
are enabled.  Now, if memory backtrace is on and you issue a
"memory show allocations" CLI command for a specific file, then
a backtrace will show for each allocation that occurred after
you turned "memory backtrace on".  The backtrace display is shown
only when a specific file's allocations are displayed to prevent
a massive CLI dump of every file's allocations.

Change-Id: Ic657afc1fc6ec7205e16eb36a97a611d235a2b4f

main/astmm.c

index 3a28f5d..cb45a03 100644 (file)
@@ -188,7 +188,7 @@ AST_MUTEX_DEFINE_STATIC_NOTRACKING(reglock);
                }                                    \
        } while (0)
 
-static void print_backtrace(struct ast_bt *bt)
+static void print_backtrace(struct ast_bt *bt, struct ast_cli_args *a)
 {
        int i = 0;
        struct ast_vector_string *strings;
@@ -198,9 +198,17 @@ static void print_backtrace(struct ast_bt *bt)
        }
 
        if ((strings = ast_bt_get_symbols(bt->addresses, bt->num_frames))) {
-               astmm_log("Memory allocation backtrace:\n");
+               if (a) {
+                       ast_cli(a->fd, "Memory allocation backtrace:\n");
+               } else {
+                       astmm_log("Memory allocation backtrace:\n");
+               }
                for (i = 3; i < AST_VECTOR_SIZE(strings) - 2; i++) {
-                       astmm_log("#%d: %s\n", i - 3, AST_VECTOR_GET(strings, i));
+                       if (a) {
+                               ast_cli(a->fd, "#%d: %s\n", i - 3, AST_VECTOR_GET(strings, i));
+                       } else {
+                               astmm_log("#%d: %s\n", i - 3, AST_VECTOR_GET(strings, i));
+                       }
                }
                ast_bt_free_symbols(strings);
        }
@@ -314,7 +322,7 @@ static void region_data_check(struct ast_region *reg)
                if (*pos != FREED_MAGIC) {
                        astmm_log("WARNING: Memory corrupted after free of %p allocated at %s %s() line %d\n",
                                reg->data, reg->file, reg->func, reg->lineno);
-                       print_backtrace(reg->bt);
+                       print_backtrace(reg->bt, NULL);
                        my_do_crash();
                        break;
                }
@@ -434,14 +442,14 @@ static void region_check_fences(struct ast_region *reg)
        if (*fence != FENCE_MAGIC) {
                astmm_log("WARNING: Low fence violation of %p allocated at %s %s() line %d\n",
                        reg->data, reg->file, reg->func, reg->lineno);
-               print_backtrace(reg->bt);
+               print_backtrace(reg->bt, NULL);
                my_do_crash();
        }
        fence = (unsigned int *) (reg->data + reg->len);
        if (get_unaligned_uint32(fence) != FENCE_MAGIC) {
                astmm_log("WARNING: High fence violation of %p allocated at %s %s() line %d\n",
                        reg->data, reg->file, reg->func, reg->lineno);
-               print_backtrace(reg->bt);
+               print_backtrace(reg->bt, NULL);
                my_do_crash();
        }
 }
@@ -880,6 +888,9 @@ static char *handle_memory_show_allocations(struct ast_cli_entry *e, int cmd, st
                        ast_cli(a->fd, "%10u bytes allocated%s by %20s() line %5u of %s\n",
                                (unsigned int) reg->len, reg->cache ? " (cache)" : "",
                                reg->func, reg->lineno, reg->file);
+                       if (reg->bt && !ast_strlen_zero(fn)) {
+                               print_backtrace(reg->bt, a);
+                       }
 
                        selected_len += reg->len;
                        if (reg->cache) {