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:
parent
d7ee492fc4
commit
bcd1ebf260
|
@ -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__
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue