commit 62f0e08bbf82d768a2ef87af44b67b5547558d2f
parent 8f191a4cad7365c97247c822c482e1afda3f5b33
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Wed, 25 May 2022 18:22:06 +0200
libc: Don't use atexit() to flush streams
__putc() was using atexit() to install a handler to flush
all the output streams, but this could drive to wrong behavioud
because we cannot guarantee that handlers installed before calling
__putc() are not going to buffer anything to output streams.
Diffstat:
3 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/src/libc/libc.h b/src/libc/libc.h
@@ -56,3 +56,4 @@ extern struct tzone tzones[];
extern void (*_exitf[])(void);
extern unsigned _exitn;
+extern void (*_flushall)(void);
diff --git a/src/libc/stdio/__putc.c b/src/libc/stdio/__putc.c
@@ -13,8 +13,6 @@ cleanup(void)
int
__putc(int ch, FILE *fp)
{
- static int first = 1;
-
if (fp->flags & _IOERR)
return EOF;
@@ -29,15 +27,7 @@ __putc(int ch, FILE *fp)
if (fp->buf == NULL && _allocbuf(fp))
return EOF;
-
- if (first) {
- if (atexit(cleanup)) {
- fp->flags |= _IOERR;
- errno = ENOMEM;
- return EOF;
- }
- first = 0;
- }
+ _flushall = cleanup;
if (fp->flags & _IOLBF) {
if (fp->wp == fp->lp && _flsbuf(fp))
diff --git a/src/libc/stdlib/exit.c b/src/libc/stdlib/exit.c
@@ -1,17 +1,20 @@
#include <stdlib.h>
#include "../libc.h"
+#include "../syscall.h"
#undef exit
void (*_exitf[_ATEXIT_MAX])(void);
unsigned _exitn;
+void (*_flushall)(void);
void
exit(int status)
{
while (_exitn > 0)
(*_exitf[--_exitn])();
-
- _Exit(status);
+ if (_flushall)
+ (*_flushall)();
+ _exit(status);
}