summaryrefslogtreecommitdiffstats
path: root/txr.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-06-05 17:56:31 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-06-05 17:56:31 -0700
commit16305b28e7bd92a6f25610095d626d492020f3ee (patch)
tree372717339a172956afe858f17f0c556502cd1b30 /txr.c
parentf407a269b7db5509fd5e36abc4b1de67e281bdd1 (diff)
downloadtxr-16305b28e7bd92a6f25610095d626d492020f3ee.tar.gz
txr-16305b28e7bd92a6f25610095d626d492020f3ee.tar.bz2
txr-16305b28e7bd92a6f25610095d626d492020f3ee.zip
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.
Diffstat (limited to 'txr.c')
-rw-r--r--txr.c27
1 files changed, 13 insertions, 14 deletions
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)