From 8700224e98f95807d896d214380796e6f80678d0 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 23 Nov 2025 13:58:37 -0500 Subject: use exit() instead of _exit() --- src/stdlib/stdlib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/stdlib/stdlib.c') diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c index 45a4bd00..157dbfd4 100644 --- a/src/stdlib/stdlib.c +++ b/src/stdlib/stdlib.c @@ -145,7 +145,7 @@ void say(Text_t text, bool newline) { public _Noreturn void tomo_exit(Text_t text, int32_t status) { if (text.length > 0) print(text); - _exit(status); + exit(status); } public -- cgit v1.2.3 From 2a24b0a3fc3c4986572ae2c4ea0e8e387497a7f6 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 23 Nov 2025 14:19:04 -0500 Subject: Add `at_cleanup()` function --- src/stdlib/stdlib.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'src/stdlib/stdlib.c') 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); + } +} -- cgit v1.2.3 From 8b897851facaa177e2346e0d97fcba7411dfc0aa Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Thu, 27 Nov 2025 12:35:52 -0500 Subject: Update `setenv()` to take an optional value, also bugfix for `setenv()` returning a value. --- src/stdlib/stdlib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/stdlib/stdlib.c') diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c index 21547efe..8ec9e90b 100644 --- a/src/stdlib/stdlib.c +++ b/src/stdlib/stdlib.c @@ -219,7 +219,10 @@ 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); } +void setenv_text(Text_t name, OptionalText_t value) { + if (value.tag == TEXT_NONE) unsetenv(Text$as_c_string(name)); + else setenv(Text$as_c_string(name), Text$as_c_string(value), 1); +} typedef struct cleanup_s { Closure_t cleanup_fn; -- cgit v1.2.3 From 08c47e1fabd1a2fb43c18828db8ad845f7db3a99 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 7 Dec 2025 23:08:08 -0500 Subject: More correct handling for sleep() --- src/stdlib/stdlib.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/stdlib/stdlib.c') diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c index 8ec9e90b..defb263c 100644 --- a/src/stdlib/stdlib.c +++ b/src/stdlib/stdlib.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -205,11 +206,16 @@ cleanup: } public -void sleep_num(double seconds) { +void sleep_seconds(double seconds) { + if (seconds < 0) fail("Cannot sleep for a negative amount of time: ", seconds); + else if (isnan(seconds)) fail("Cannot sleep for a time that is NaN"); struct timespec ts; ts.tv_sec = (time_t)seconds; ts.tv_nsec = (long)((seconds - (double)ts.tv_sec) * 1e9); - nanosleep(&ts, NULL); + while (nanosleep(&ts, NULL) != 0) { + if (errno == EINTR) continue; + fail("Failed to sleep for the requested time (", strerror(errno), ")"); + } } public -- cgit v1.2.3 From 86228917b98a3ef4019e9e18fcafacc948ffcfd1 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 7 Dec 2025 23:12:33 -0500 Subject: Better error handling for setenv() --- src/stdlib/stdlib.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'src/stdlib/stdlib.c') diff --git a/src/stdlib/stdlib.c b/src/stdlib/stdlib.c index defb263c..f4e6d678 100644 --- a/src/stdlib/stdlib.c +++ b/src/stdlib/stdlib.c @@ -226,8 +226,16 @@ OptionalText_t getenv_text(Text_t name) { public void setenv_text(Text_t name, OptionalText_t value) { - if (value.tag == TEXT_NONE) unsetenv(Text$as_c_string(name)); - else setenv(Text$as_c_string(name), Text$as_c_string(value), 1); + int status; + if (value.tag == TEXT_NONE) { + status = unsetenv(Text$as_c_string(name)); + } else { + status = setenv(Text$as_c_string(name), Text$as_c_string(value), 1); + } + if (status != 0) { + if (errno == EINVAL) fail("Invalid environment variable name: ", Text$quoted(name, false, Text("\""))); + else fail("Failed to set environment variable (", strerror(errno)); + } } typedef struct cleanup_s { -- cgit v1.2.3