diff --git a/lib/std/libc/libc.c3 b/lib/std/libc/libc.c3 index 1f1a6aeb1..f21c6df5e 100644 --- a/lib/std/libc/libc.c3 +++ b/lib/std/libc/libc.c3 @@ -97,6 +97,7 @@ extern fn CInt close(CInt fd) @if(!env::WIN32); extern fn double difftime(Time_t time1, Time_t time2) @if(!env::WIN32); extern fn DivResult div(CInt numer, CInt denom); extern fn void exit(CInt status); +extern fn void _exit(CInt status) @extern("_Exit"); extern fn CInt fclose(CFile stream); extern fn CFile fdopen(CInt fd, ZString mode) @if(!env::WIN32); extern fn CInt feof(CFile stream); diff --git a/lib/std/libc/os/errno.c3 b/lib/std/libc/os/errno.c3 index c5db365f9..1fb2ec008 100644 --- a/lib/std/libc/os/errno.c3 +++ b/lib/std/libc/os/errno.c3 @@ -1,4 +1,4 @@ -module libc::os; +module libc::os @if(env::LIBC); // Linux extern fn int* __errno_location() @if(env::LINUX); @@ -22,7 +22,7 @@ extern fn void _get_errno(int* result) @if(env::WIN32); extern fn void _set_errno(int err) @if(env::WIN32); // Default -const ERRNO_DEFAULT @local = !env::LINUX && !env::DARWIN && !env::WIN32; -tlocal int _errno_c3 @if(ERRNO_DEFAULT) = 0; -fn void errno_set(int err) @if(ERRNO_DEFAULT) => _errno_c3 = err; -fn int errno() @if(ERRNO_DEFAULT) => _errno_c3; +module libc::os @if(!env::LIBC || !(env::LINUX || env::DARWIN || env::WIN32)); +tlocal int _errno_c3 = 0; +fn void errno_set(int err) => _errno_c3 = err; +fn int errno() => _errno_c3; diff --git a/lib/std/os/os.c3 b/lib/std/os/os.c3 new file mode 100644 index 000000000..e7cab9a6d --- /dev/null +++ b/lib/std/os/os.c3 @@ -0,0 +1,27 @@ +module std::os; +import libc; + +<* + Exit the process with a given exit code. This will typically call 'exit' in LibC +*> +fn void exit(int result, bool cleanup = true) @weak +{ + $if env::LIBC: + libc::exit(result); + $else + $$trap(); + $endif +} + +<* + Exit the process with a given exit code. This will typically call '_Exit' in LibC + usually bypassing '@finalizer' functions. +*> +fn void fastexit(int result, bool cleanup = true) @weak +{ + $if env::LIBC: + libc::_exit(result); + $else + $$trap(); + $endif +} diff --git a/releasenotes.md b/releasenotes.md index 3a4ff6241..96210899f 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -75,6 +75,7 @@ - `AnyList` now also defaults to the temp allocator. - `os::getcwd` and `os::get_home_dir` requires an explicit allocator. - `file::load_new` and `file::load_path_new` removed. +- `os::exit` and `os::fastexit` added. ## 0.6.8 Change list diff --git a/test/src/test_suite_runner.c3 b/test/src/test_suite_runner.c3 index e6dc3b31e..96437346d 100644 --- a/test/src/test_suite_runner.c3 +++ b/test/src/test_suite_runner.c3 @@ -86,7 +86,7 @@ fn void main(String[] args) io::printfn("Found %d tests: %.1f%% (%d / %d) passed (%d skipped).", test_count, (100.0 * success_count) / math::max(1, test_count - skip_count), success_count, test_count - skip_count, skip_count); - libc::exit(success_count == test_count - skip_count ? 0 : 1); + os::exit(success_count == test_count - skip_count ? 0 : 1); } struct Error @@ -346,7 +346,7 @@ fn void parse_header_directive(int* line_no, String line, RunSettings* settings, settings.output_files.push(file); default: io::printfn("FAILED - Unknown header directive '%s'", line); - libc::exit(1); + os::exit(1); } } @@ -528,7 +528,7 @@ fn void usage(String appname) @noreturn io::printn("Options:"); io::printn(" -s, --skipped only run skipped tests"); io::printn(" --stdlib override the path to stdlib"); - libc::exit(0); + os::exit(0); } fn void arg_error_exit(String appname, String fmt, args...) @noreturn