From ac0604a4d4a29423027deef3ff9670b877c9ac32 Mon Sep 17 00:00:00 2001 From: herman ten brugge Date: Tue, 29 Nov 2022 21:13:20 +0100 Subject: [PATCH] Allow atexit to be used with -run Add atexit code to tccrun.c and added testcase 128 --- tccrun.c | 29 +++++++++++++++++++++++++++++ tests/tests2/128_run_atexit.c | 20 ++++++++++++++++++++ tests/tests2/128_run_atexit.expect | 2 ++ 3 files changed, 51 insertions(+) create mode 100644 tests/tests2/128_run_atexit.c create mode 100644 tests/tests2/128_run_atexit.expect diff --git a/tccrun.c b/tccrun.c index 826e52ca..064af300 100644 --- a/tccrun.c +++ b/tccrun.c @@ -54,6 +54,9 @@ static rt_context g_rtctxt; static void set_exception_handler(void); static int _rt_error(void *fp, void *ip, const char *fmt, va_list ap); static void rt_exit(int code); +static void init_atexit(void); +static void run_atexit(void); +static int rt_atexit(void (*function)(void)); #endif /* CONFIG_TCC_BACKTRACE */ /* defined when included from lib/bt-exe.c */ @@ -169,6 +172,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) if (s1->do_debug) tcc_add_symbol(s1, "exit", rt_exit); #endif + tcc_add_symbol(s1, "atexit", rt_atexit); if (tcc_relocate(s1, TCC_RELOCATE_AUTO) < 0) return -1; prog_main = (void*)get_sym_addr(s1, s1->runtime_main, 1, 1); @@ -215,6 +219,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) errno = 0; /* clean errno value */ fflush(stdout); fflush(stderr); + init_atexit(); /* These aren't C symbols, so don't need leading underscore handling. */ run_cdtors(s1, "__init_array_start", "__init_array_end", argc, argv, envp); #ifdef CONFIG_TCC_BACKTRACE @@ -224,6 +229,7 @@ LIBTCCAPI int tcc_run(TCCState *s1, int argc, char **argv) ret = prog_main(argc, argv, envp); } run_cdtors(s1, "__fini_array_start", "__fini_array_end", 0, NULL, NULL); + run_atexit(); if ((s1->dflag & 16) && ret) fprintf(s1->ppfp, "[returns %d]\n", ret), fflush(s1->ppfp); return ret; @@ -1022,6 +1028,29 @@ static void rt_exit(int code) exit(code); } +#define NR_AT_EXIT 32 + +static int nr_atexit = 0; +static void (*at_exitfunc[NR_AT_EXIT])(void); + +static void init_atexit(void) +{ + nr_atexit = 0; +} + +static void run_atexit(void) +{ + while (nr_atexit) + at_exitfunc[--nr_atexit](); +} + +static int rt_atexit(void (*function)(void)) +{ + if (nr_atexit < NR_AT_EXIT) + at_exitfunc[nr_atexit++] = function; + return 1; +} + /* ------------------------------------------------------------- */ #ifndef _WIN32 diff --git a/tests/tests2/128_run_atexit.c b/tests/tests2/128_run_atexit.c new file mode 100644 index 00000000..f8fc391d --- /dev/null +++ b/tests/tests2/128_run_atexit.c @@ -0,0 +1,20 @@ +#include +#include + +void cleanup1(void) +{ + printf ("cleanup1\n"); +} + +void cleanup2(void) +{ + printf ("cleanup2\n"); +} + +int main(int argc, char **argv) +{ + atexit(cleanup1); + atexit(cleanup2); + return 0; +} + diff --git a/tests/tests2/128_run_atexit.expect b/tests/tests2/128_run_atexit.expect new file mode 100644 index 00000000..35df70c9 --- /dev/null +++ b/tests/tests2/128_run_atexit.expect @@ -0,0 +1,2 @@ +cleanup2 +cleanup1