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 <xiaoxiang@xiaomi.com>
This commit is contained in:
Xiang Xiao 2023-01-21 00:23:16 +08:00 committed by Petro Karashchenko
parent d7ee492fc4
commit bcd1ebf260
5 changed files with 118 additions and 6 deletions

View File

@ -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__

View File

@ -26,6 +26,7 @@
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <stdlib.h>
/****************************************************************************
@ -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)

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);