scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/libc/libc.h | 1+
Msrc/libc/stdio/__putc.c | 12+-----------
Msrc/libc/stdlib/exit.c | 7+++++--
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); }