shithub: scc

Download patch

ref: e60ffe8d64ff9670fdf5ac0efb7fd64ff08af8bc
parent: 020a6282c06e9f61517d8a37495d888ec7527808
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Mar 7 15:56:46 EST 2017

[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.

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