From 743aedcd495fadd583846426a417b6c5d9699ec0 Mon Sep 17 00:00:00 2001 From: apio Date: Wed, 12 Oct 2022 20:41:55 +0200 Subject: [PATCH] libc: Implement atexit() and _exit() exit() now calls registered handlers before calling _exit(). And initialize_libc() can now register a handler to close stdout and stderr on program termination!! :) --- libs/libc/include/stdlib.h | 6 +++--- libs/libc/include/unistd.h | 4 ++++ libs/libc/src/atexit.cpp | 25 +++++++++++++++++++++++++ libs/libc/src/init.cpp | 7 +++++++ libs/libc/src/stdlib.cpp | 13 +------------ libs/libc/src/unistd.cpp | 6 ++++++ 6 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 libs/libc/src/atexit.cpp diff --git a/libs/libc/include/stdlib.h b/libs/libc/include/stdlib.h index f8380026..cde4fa34 100644 --- a/libs/libc/include/stdlib.h +++ b/libs/libc/include/stdlib.h @@ -12,11 +12,11 @@ extern "C" /* Aborts the program. */ noreturn void abort(); - /* Exits the program with the specified status code. */ + /* Normally exits the program with the specified status code. */ noreturn void exit(int status); - /* Not implemented. */ - int atexit(void (*)(void)); + /* Registers a handler function to be run at normal program termination. */ + int atexit(void (*handler)(void)); /* Not implemented.*/ int atoi(const char*); diff --git a/libs/libc/include/unistd.h b/libs/libc/include/unistd.h index 871b3646..f86abe77 100644 --- a/libs/libc/include/unistd.h +++ b/libs/libc/include/unistd.h @@ -1,6 +1,7 @@ #ifndef _UNISTD_H #define _UNISTD_H +#include #include #include @@ -20,6 +21,9 @@ extern "C" /* Not implemented. */ pid_t fork(void); + /* Terminates the program with the status code status. */ + noreturn void _exit(int status); + /* Calls the kernel for a specific service, determined by number. */ long syscall(long number, ...); diff --git a/libs/libc/src/atexit.cpp b/libs/libc/src/atexit.cpp new file mode 100644 index 00000000..8df2a117 --- /dev/null +++ b/libs/libc/src/atexit.cpp @@ -0,0 +1,25 @@ +#include +#include + +#define ATEXIT_MAX_FUNCS 32 + +typedef void (*atexit_func_t)(void); + +atexit_func_t atexit_functions[ATEXIT_MAX_FUNCS]; +int atexit_function_count = 0; + +extern "C" +{ + int atexit(atexit_func_t handler) + { + if (atexit_function_count >= ATEXIT_MAX_FUNCS) return -1; + atexit_functions[atexit_function_count++] = handler; + return 0; + } + + noreturn void exit(int status) + { + for (int i = 0; i < atexit_function_count; i++) { atexit_functions[i](); } + _exit(status); + } +} \ No newline at end of file diff --git a/libs/libc/src/init.cpp b/libs/libc/src/init.cpp index c77def4e..24df6f78 100644 --- a/libs/libc/src/init.cpp +++ b/libs/libc/src/init.cpp @@ -4,6 +4,12 @@ #include #include +static void terminate_libc() +{ + fclose(stdout); + fclose(stderr); +} + extern "C" void initialize_libc() { if (lseek(0, 0, SEEK_CUR) < 0) @@ -24,4 +30,5 @@ extern "C" void initialize_libc() errno = 0; } else { stderr = fdopen(1, "rw"); } + atexit(terminate_libc); } \ No newline at end of file diff --git a/libs/libc/src/stdlib.cpp b/libs/libc/src/stdlib.cpp index 9841f6de..f05cf891 100644 --- a/libs/libc/src/stdlib.cpp +++ b/libs/libc/src/stdlib.cpp @@ -7,18 +7,7 @@ extern "C" { noreturn void abort() { - exit(-1); - } - - noreturn void exit(int status) - { - syscall(SYS_exit, status); - __builtin_unreachable(); - } - - int atexit(void (*)(void)) - { - NOT_IMPLEMENTED("atexit"); + _exit(-1); } int atoi(const char*) diff --git a/libs/libc/src/unistd.cpp b/libs/libc/src/unistd.cpp index 8b1da12e..21efc6ea 100644 --- a/libs/libc/src/unistd.cpp +++ b/libs/libc/src/unistd.cpp @@ -95,4 +95,10 @@ extern "C" { return syscall(SYS_seek, fd, offset, whence); } + + noreturn void _exit(int status) + { + syscall(SYS_exit, status); + __builtin_unreachable(); + } } \ No newline at end of file