summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2019-12-07 00:06:05 +0100
committerAndrei Karas <akaras@inbox.ru>2020-03-30 06:35:10 +0300
commit8f38bf7f9e402edc14df3fe89dc0b46b1b1c3ee9 (patch)
tree3fbe3311ff50b1d66a32ead39678bdda7d8b1ae4
parent80372d4ca082d6d35f89e99094544fc892cfeb75 (diff)
downloadhercules-8f38bf7f9e402edc14df3fe89dc0b46b1b1c3ee9.tar.gz
hercules-8f38bf7f9e402edc14df3fe89dc0b46b1b1c3ee9.tar.bz2
hercules-8f38bf7f9e402edc14df3fe89dc0b46b1b1c3ee9.tar.xz
hercules-8f38bf7f9e402edc14df3fe89dc0b46b1b1c3ee9.zip
Fix a memory leak caused by repeatedly allocating the libbacktrace state at every printed backtrace
Signed-off-by: Haru <haru@dotalux.com>
-rw-r--r--src/common/core.c2
-rw-r--r--src/common/nullpo.c34
-rw-r--r--src/common/nullpo.h7
3 files changed, 32 insertions, 11 deletions
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