From bcd1ebf26056fb1ebbd0abfdd081c1568f299d32 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sat, 21 Jan 2023 00:23:16 +0800 Subject: [PATCH] libc: Implement quick_exit and at_quick_exit Defined by c11: https://en.cppreference.com/w/c/program/quick_exit https://en.cppreference.com/w/c/program/at_quick_exit Signed-off-by: Xiang Xiao --- include/cxx/cstdlib | 2 + include/nuttx/atexit.h | 6 ++- include/stdlib.h | 2 + libs/libc/stdlib/lib_atexit.c | 31 +++++++++++-- libs/libc/stdlib/lib_exit.c | 83 ++++++++++++++++++++++++++++++++++- 5 files changed, 118 insertions(+), 6 deletions(-) diff --git a/include/cxx/cstdlib b/include/cxx/cstdlib index 51bc3d8d26..34483cdf9c 100644 --- a/include/cxx/cstdlib +++ b/include/cxx/cstdlib @@ -51,8 +51,10 @@ namespace std // Process exit functions using ::exit; + using ::quick_exit; using ::abort; using ::atexit; + using ::at_quick_exit; using ::on_exit; #ifndef __KERNEL__ diff --git a/include/nuttx/atexit.h b/include/nuttx/atexit.h index ad511290b5..84a0167f3a 100644 --- a/include/nuttx/atexit.h +++ b/include/nuttx/atexit.h @@ -26,6 +26,7 @@ ****************************************************************************/ #include +#include #include /**************************************************************************** @@ -44,6 +45,7 @@ enum atexit_type_e { ATTYPE_NONE, ATTYPE_ATEXIT, + ATTYPE_ATQUICKEXIT, ATTYPE_ONEXIT, ATTYPE_CXA }; @@ -106,10 +108,10 @@ int atexit_register(int type, CODE void (*func)(void), FAR void *arg, * ****************************************************************************/ -void atexit_call_exitfuncs(int status); +void atexit_call_exitfuncs(int status, bool quick); #else # define atexit_register(type, func, arg, dso) (0) -# define atexit_call_exitfuncs(status) +# define atexit_call_exitfuncs(status, quick) #endif /* CONFIG_LIBC_MAX_EXITFUNS */ #if defined(__cplusplus) diff --git a/include/stdlib.h b/include/stdlib.h index a522680a65..5e90eb5d08 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -166,8 +166,10 @@ int unsetenv(FAR const char *name); /* Process exit functions */ void exit(int status) noreturn_function; +void quick_exit(int status) noreturn_function; void abort(void) noreturn_function; int atexit(CODE void (*func)(void)); +int at_quick_exit(CODE void (*func)(void)); int on_exit(CODE void (*func)(int, FAR void *), FAR void *arg); /* _Exit() is a stdlib.h equivalent to the unistd.h _exit() function */ diff --git a/libs/libc/stdlib/lib_atexit.c b/libs/libc/stdlib/lib_atexit.c index 0486cdf63b..eab0894667 100644 --- a/libs/libc/stdlib/lib_atexit.c +++ b/libs/libc/stdlib/lib_atexit.c @@ -50,7 +50,7 @@ * ****************************************************************************/ -static FAR struct atexit_list_s * get_exitfuncs(void) +static FAR struct atexit_list_s *get_exitfuncs(void) { FAR struct task_info_s *info; @@ -105,7 +105,7 @@ int atexit_register(int type, CODE void (*func)(void), FAR void *arg, return ret; } -void atexit_call_exitfuncs(int status) +void atexit_call_exitfuncs(int status, bool quick) { FAR struct atexit_list_s *aehead; CODE void (*func)(void); @@ -134,9 +134,14 @@ void atexit_call_exitfuncs(int status) continue; } + if (quick != (type == ATTYPE_ATQUICKEXIT)) + { + continue; + } + /* Call the atexit/on_exit/cxa_atexit() function */ - if (type == ATTYPE_ATEXIT) + if (type == ATTYPE_ATEXIT || type == ATTYPE_ATQUICKEXIT) { (*func)(); } @@ -181,3 +186,23 @@ int atexit(CODE void (*func)(void)) { return atexit_register(ATTYPE_ATEXIT, func, NULL, NULL); } + +/**************************************************************************** + * Name: at_quick_exit + * + * Description: + * Registers the function pointed to by func to be called on quick + * program termination (via quick_exit). + * + * Input Parameters: + * func - A pointer to the function to be called when the task exits. + * + * Returned Value: + * Zero on success. Non-zero on failure. + * + ****************************************************************************/ + +int at_quick_exit(CODE void (*func)(void)) +{ + return atexit_register(ATTYPE_ATQUICKEXIT, func, NULL, NULL); +} diff --git a/libs/libc/stdlib/lib_exit.c b/libs/libc/stdlib/lib_exit.c index c2e81206c5..2cef9eff1b 100644 --- a/libs/libc/stdlib/lib_exit.c +++ b/libs/libc/stdlib/lib_exit.c @@ -46,11 +46,47 @@ FAR void *__dso_handle = &__dso_handle; * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: exit + * + * Description: + * The exit() function causes normal process termination and the + * least significant byte of status (i.e., status & 0xFF) is + * returned to the parent (see wait(2)). + * + * All functions registered with atexit(3) and on_exit(3) are + * called, in the reverse order of their registration. (It is + * possible for one of these functions to use atexit(3) or + * on_exit(3) to register an additional function to be executed + * during exit processing; the new registration is added to the + * front of the list of functions that remain to be called.) If one + * of these functions does not return (e.g., it calls _exit(2), or + * kills itself with a signal), then none of the remaining functions + * is called, and further exit processing (in particular, flushing + * of stdio(3) streams) is abandoned. If a function has been + * registered multiple times using atexit(3) or on_exit(3), then it + * is called as many times as it was registered. + * + * All open stdio(3) streams are flushed and closed. Files created + * by tmpfile(3) are removed. + * + * The C standard specifies two constants, EXIT_SUCCESS and + * EXIT_FAILURE, that may be passed to exit() to indicate successful + * or unsuccessful termination, respectively. + * + * Input Parameters: + * status - Exit status code + * + * Returned Value: + * Does not return. + * + ****************************************************************************/ + void exit(int status) { /* Run the registered exit functions */ - atexit_call_exitfuncs(status); + atexit_call_exitfuncs(status, false); /* Flush all streams */ @@ -61,6 +97,51 @@ void exit(int status) _exit(status); } +/**************************************************************************** + * Name: quick_exit + * + * Description: + * The quick_exit() function exits the program quickly calling any cleanup + * functions registered with at_quick_exit(3) but not any C++ destructors + * or cleanup code registered with atexit(3). The stdio(3) file buffers + * are not flushed. + * + * Input Parameters: + * status - Exit status code + * + * Returned Value: + * Does not return. + * + ****************************************************************************/ + +void quick_exit(int status) +{ + /* Run the registered exit functions */ + + atexit_call_exitfuncs(status, true); + + /* Then perform the exit */ + + _exit(status); +} + +/**************************************************************************** + * Name: _Exit + * + * Description: + * The _Exit() functions shall not call functions registered with atexit() + * nor any registered signal handlers. Open streams shall not be flushed. + * Whether open streams are closed (without flushing) is implementation + * defined. + * + * Input Parameters: + * status - Exit status code + * + * Returned Value: + * Does not return. + * + ****************************************************************************/ + void _Exit(int status) { _exit(status);