From 8f38bf7f9e402edc14df3fe89dc0b46b1b1c3ee9 Mon Sep 17 00:00:00 2001 From: Haru Date: Sat, 7 Dec 2019 00:06:05 +0100 Subject: Fix a memory leak caused by repeatedly allocating the libbacktrace state at every printed backtrace Signed-off-by: Haru --- src/common/core.c | 2 ++ src/common/nullpo.c | 34 +++++++++++++++++++++++----------- src/common/nullpo.h | 7 +++++++ 3 files changed, 32 insertions(+), 11 deletions(-) (limited to 'src/common') diff --git a/src/common/core.c b/src/common/core.c index 54358b85c..5be90a411 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -489,6 +489,7 @@ int main(int argc, char **argv) iMalloc->init();// needed for Show* in display_title() [FlavioJS] showmsg->init(); + nullpo->init(); cmdline->init(); @@ -552,6 +553,7 @@ int main(int argc, char **argv) cmdline->final(); //sysinfo->final(); Called by iMalloc->final() + nullpo->final(); iMalloc->final(); showmsg->final(); // Should be after iMalloc->final() diff --git a/src/common/nullpo.c b/src/common/nullpo.c index e43b91bb8..d28d7ee4b 100644 --- a/src/common/nullpo.c +++ b/src/common/nullpo.c @@ -74,12 +74,6 @@ static void nullpo_backtrace_print(struct backtrace_state *state) */ static void assert_report(const char *file, int line, const char *func, const char *targetname, const char *title) { -#if !defined(HAVE_LIBBACKTRACE) && defined(HAVE_EXECINFO) - void *array[10]; - int size; - char **strings; - int i; -#endif // !defined(HAVE_LIBBACKTRACE) && defined(HAVE_EXECINFO) if (file == NULL) file = "??"; @@ -89,17 +83,31 @@ static void assert_report(const char *file, int line, const char *func, const ch ShowError("--- %s --------------------------------------------\n", title); ShowError("%s:%d: '%s' in function `%s'\n", file, line, targetname, func); #ifdef HAVE_LIBBACKTRACE - struct backtrace_state *state = backtrace_create_state("hercules", BACKTRACE_SUPPORTS_THREADS, nullpo_error_callback, NULL); - nullpo_backtrace_print(state); + if (nullpo->backtrace_state != NULL) + nullpo_backtrace_print(nullpo->backtrace_state); #elif defined(HAVE_EXECINFO) - size = (int)backtrace(array, 10); - strings = backtrace_symbols(array, size); - for (i = 0; i < size; i++) + void *array[10]; + int size = (int)backtrace(array, 10); + char **strings = backtrace_symbols(array, size); + for (int i = 0; i < size; i++) ShowError("%s\n", strings[i]); free(strings); #endif // HAVE_LIBBACKTRACE ShowError("--- end %s ----------------------------------------\n", title); +} +static void nullpo_init(void) +{ +#ifdef HAVE_LIBBACKTRACE + nullpo->backtrace_state = backtrace_create_state("hercules", BACKTRACE_SUPPORTS_THREADS, nullpo_error_callback, NULL); +#endif +} + +static void nullpo_final(void) +{ + // FIXME: libbacktrace doesn't provide a backtrace_free_state, and it's unsafe to pass the state to + // backtrace_free (the function itself uses the state internally). For the time being, we'll leave the state + // allocated until program termination as shown in their examples. } /** @@ -108,5 +116,9 @@ static void assert_report(const char *file, int line, const char *func, const ch void nullpo_defaults(void) { nullpo = &nullpo_s; + nullpo->init = nullpo_init; + nullpo->final = nullpo_final; nullpo->assert_report = assert_report; + + nullpo->backtrace_state = NULL; } diff --git a/src/common/nullpo.h b/src/common/nullpo.h index fc5386243..3eb002834 100644 --- a/src/common/nullpo.h +++ b/src/common/nullpo.h @@ -28,6 +28,8 @@ // if need disable asserts checks this line can be commented #define ASSERT_CHECK +struct backtrace_state; + /** Assert */ #if defined(ASSERT_CHECK) @@ -148,7 +150,12 @@ struct nullpo_interface { + void (*init) (void); + void (*final) (void); + void (*assert_report) (const char *file, int line, const char *func, const char *targetname, const char *title); + + struct backtrace_state *backtrace_state; }; #ifdef HERCULES_CORE -- cgit v1.2.3-70-g09d2