diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2025-11-23 14:19:04 -0500 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2025-11-23 14:22:22 -0500 |
| commit | 2a24b0a3fc3c4986572ae2c4ea0e8e387497a7f6 (patch) | |
| tree | 539d7bb993b8b9aca1935b3afb21ba0a6cba241c /src/stdlib | |
| parent | 8700224e98f95807d896d214380796e6f80678d0 (diff) | |
Add `at_cleanup()` function
Diffstat (limited to 'src/stdlib')
| -rw-r--r-- | src/stdlib/stdlib.c | 23 | ||||
| -rw-r--r-- | src/stdlib/stdlib.h | 4 |
2 files changed, 27 insertions, 0 deletions
diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c index 157dbfd4..21547efe 100644 --- a/src/stdlib/stdlib.c +++ b/src/stdlib/stdlib.c @@ -72,6 +72,7 @@ void tomo_init(void) { sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGILL, &sigact, (struct sigaction *)NULL); + atexit(tomo_cleanup); } public @@ -219,3 +220,25 @@ OptionalText_t getenv_text(Text_t name) { public void setenv_text(Text_t name, Text_t value) { setenv(Text$as_c_string(name), Text$as_c_string(value), 1); } + +typedef struct cleanup_s { + Closure_t cleanup_fn; + struct cleanup_s *next; +} cleanup_t; + +static cleanup_t *cleanups = NULL; + +public +void tomo_at_cleanup(Closure_t fn) { cleanups = new (cleanup_t, .cleanup_fn = fn, .next = cleanups); } + +public +void tomo_cleanup(void) { + while (cleanups) { + // NOTE: we *must* remove the cleanup function from the stack before calling it, + // otherwise it will cause an infinite loop if the cleanup function fails or exits. + void (*run_cleanup)(void *) = cleanups->cleanup_fn.fn; + void *userdata = cleanups->cleanup_fn.userdata; + cleanups = cleanups->next; + run_cleanup(userdata); + } +} diff --git a/src/stdlib/stdlib.h b/src/stdlib/stdlib.h index aadce27c..392b5f23 100644 --- a/src/stdlib/stdlib.h +++ b/src/stdlib/stdlib.h @@ -16,9 +16,12 @@ extern bool USE_COLOR; extern Text_t TOMO_VERSION_TEXT; void tomo_init(void); +void tomo_at_cleanup(Closure_t fn); +void tomo_cleanup(void); #define fail(...) \ ({ \ + tomo_cleanup(); \ fflush(stdout); \ if (USE_COLOR) fputs("\x1b[31;7m ==================== ERROR ==================== \033[m\n\n", stderr); \ else fputs("==================== ERROR ====================\n\n", stderr); \ @@ -35,6 +38,7 @@ void tomo_init(void); #define fail_source(filename, start, end, ...) \ ({ \ + tomo_cleanup(); \ fflush(stdout); \ if (USE_COLOR) fputs("\x1b[31;7m ==================== ERROR ==================== \n\n\x1b[0;1m", stderr); \ else fputs("==================== ERROR ====================\n\n", stderr); \ |
