commit 33b9f7476c6f730def0034b2b36ad14dde30d2f2 parent 3ddba6b6ed93c63e246397e08acdc39a2e1744a9 Author: Roberto E. Vargas Caballero <k0ga@shike2.com> Date: Tue, 7 Mar 2017 20:56:46 +0100 [libc] Fix exit() and atexit() Functions registered with atexit() must be called in reverse order. This implementation also protects against calling exit() from an atexit() handler. Diffstat:
M | libc/include/errno.h | | | 1 | + |
M | libc/src/atexit.c | | | 18 | +++++++++--------- |
M | libc/src/exit.c | | | 14 | ++++---------- |
3 files changed, 14 insertions(+), 19 deletions(-)
diff --git a/libc/include/errno.h b/libc/include/errno.h @@ -5,6 +5,7 @@ #define EDOM 1 #define EILSEQ 2 #define ERANGE 3 +#define ENOMEN 4 extern int errno; diff --git a/libc/src/atexit.c b/libc/src/atexit.c @@ -1,19 +1,19 @@ /* See LICENSE file for copyright and license details. */ #include <stdlib.h> +#include <errno.h> #undef atexit -extern void (*_atexitf[_ATEXIT_MAX])(void); +extern void (*_exitf[_ATEXIT_MAX])(void); +extern unsigned _exitn; int atexit(void (*fun)(void)) { - void (**bp)(void); - - for (bp = _atexitf; bp < &_atexitf[_ATEXIT_MAX] && *bp; ++bp) - /* nothing */; - if (bp == &_atexitf[_ATEXIT_MAX]) - return 0; - *bp = fun; - return 1; + if (_exitn == _ATEXIT_MAX) { + errno = ENOMEN; + return -1; + } + _exitf[_exitn++] = fun; + return 0; } diff --git a/libc/src/exit.c b/libc/src/exit.c @@ -3,19 +3,13 @@ #include <stdlib.h> #undef exit -void (*_atexitf[_ATEXIT_MAX])(void); +void (*_exitf[_ATEXIT_MAX])(void); +unsigned _exitn; void exit(int status) { - void (**bp)(void); - int i; - - for (i = _ATEXIT_MAX-1; i >= 0; --i) { - if (bp = _atexit[i]) { - *_atexit[i] = NULL; - (*bp)(); - } - } + while (_exitn > 0) + (*_exitf[--exitn])(); _Exit(status); }