From 9f844d7eda5b232a78379c96b61bdc01f8536744 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Sun, 5 Jun 2022 17:56:31 -0700 Subject: txr: fix --free-all crash due to atexit order. The --free-all feature is broken. It is needed for confirming lack of memory leaks during development. What breaks it is the atexit call to run_load_hooks in eval.c, which occurs after the atexit call to free_all in txr.c which blows everything away. * Makefile (tst/tests/019/load-hook.ok): Let's put --free-all on this test case, because it has to with the load hooks. Make no mistake though: everything crashes with --free-all, not this test case specifically. * txr.c (opt_free_all): New global variable. (free_all): Free resources only if opt_free_all is true. Lose the paranoid called flag. (main): Register free_all with atexit before callilng init. This ensures that it will be called after any atexit handlers registered as part of init, like the one in sysif.c and eval.c. (txr_main): The --free-all option now just sets opt_free_all. * txr.h (opt_free_all): Declared. --- Makefile | 1 + txr.c | 27 +++++++++++++-------------- txr.h | 1 + 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 698ee5a0..4ca6058f 100644 --- a/Makefile +++ b/Makefile @@ -440,6 +440,7 @@ tst/tests/016/%: TXR_DBG_OPTS := tst/tests/017/%: TXR_DBG_OPTS := tst/tests/018/%: TXR_DBG_OPTS := tst/tests/019/%: TXR_DBG_OPTS := +tst/tests/019/load-hook.ok: TXR_DBG_OPTS := --free-all tst/tests/014/dgram-stream.ok: | tst/tests/014/socket-basic.ok diff --git a/txr.c b/txr.c index dc580f1b..78f7b042 100644 --- a/txr.c +++ b/txr.c @@ -80,6 +80,7 @@ int opt_noninteractive = if_full_repl(0, 1); int opt_noprofile; int opt_compat; int opt_dbg_expansion; +int opt_free_all; val stdlib_path; #if HAVE_FORK_STUFF @@ -415,6 +416,16 @@ static int license(void) return retval; } +static void free_all(void) +{ + if (opt_free_all) { + regex_free_all(); + gc_free_all(); + arith_free_all(); + free(progname); + } +} + int txr_main(int argc, char **argv); int main(int argc, char **argv) @@ -423,6 +434,7 @@ int main(int argc, char **argv) repress_privilege(); progname = utf8_dup_from(argv[0] ? argv[0]: "txr"); progname_u8 = argv[0]; + atexit(free_all); init(&stack_bottom); match_init(); debug_init(); @@ -518,19 +530,6 @@ static int gc_delta(val optval) return 1; } -static void free_all(void) -{ - static int called; - - if (!called) { - called = 1; - regex_free_all(); - gc_free_all(); - arith_free_all(); - free(progname); - } -} - #ifndef CONFIG_DEBUG_SUPPORT static void no_dbg_support(val arg) { @@ -932,7 +931,7 @@ int txr_main(int argc, char **argv) } else if (equal(opt, lit("free-all"))) { if (org) goto noarg; - atexit(free_all); + opt_free_all = 1; continue; } else if (equal(opt, lit("noprofile"))) { if (org) diff --git a/txr.h b/txr.h index f57635bc..6570bf6a 100644 --- a/txr.h +++ b/txr.h @@ -41,6 +41,7 @@ extern int opt_debugger; extern int opt_dbg_autoload; extern int opt_dbg_expansion; extern int opt_noprofile; +extern int opt_free_all; extern alloc_bytes_t opt_gc_delta; extern const wchli_t *version; extern wchar_t *progname; -- cgit v1.2.3