From 623b0d05bd924e7fa3c155492695123c87c3a2b1 Mon Sep 17 00:00:00 2001 From: Dmitriy Ivanov Date: Wed, 14 May 2014 23:11:05 -0700 Subject: [PATCH] Register _cleanup function with atexit * Register cleanup function with atexit instead of calling it explicitly on exit() * abort() no longer calls _cleanup: Flushing stdio buffers on abort is no longer required by POSIX. * dlmalloc no longer need to reset cleanup (see above) * Upstream findfp.c makebuf.c setvbuf.cexit.c to openbsd versions. Bug: 14415367 Change-Id: I277058852485a9d3dbb13e5c232db5f9948d78ac --- libc/Android.mk | 8 ++-- libc/bionic/abort.cpp | 7 ---- libc/bionic/dlmalloc.c | 3 -- libc/stdlib/atexit.c | 42 ++++++++++++++++++- .../lib/libc}/stdio/findfp.c | 39 ++++------------- .../lib/libc/stdio/makebuf.c | 21 +++------- .../lib/libc/stdio/setvbuf.c | 21 ++++------ .../lib/libc/stdlib/exit.c | 32 ++++---------- 8 files changed, 73 insertions(+), 100 deletions(-) rename libc/{ => upstream-openbsd/lib/libc}/stdio/findfp.c (84%) rename libc/{upstream-freebsd => upstream-openbsd}/lib/libc/stdio/makebuf.c (86%) rename libc/{upstream-freebsd => upstream-openbsd}/lib/libc/stdio/setvbuf.c (90%) rename libc/{upstream-netbsd => upstream-openbsd}/lib/libc/stdlib/exit.c (76%) diff --git a/libc/Android.mk b/libc/Android.mk index 2d56af052..82dcc553e 100644 --- a/libc/Android.mk +++ b/libc/Android.mk @@ -70,7 +70,6 @@ libc_common_src_files := \ bionic/sigsetmask.c \ bionic/system_properties_compat.c \ bionic/unlockpt.c \ - stdio/findfp.c \ stdio/snprintf.c\ stdio/sprintf.c \ stdlib/atexit.c \ @@ -227,9 +226,7 @@ libc_upstream_freebsd_src_files := \ upstream-freebsd/lib/libc/stdio/fclose.c \ upstream-freebsd/lib/libc/stdio/flags.c \ upstream-freebsd/lib/libc/stdio/fopen.c \ - upstream-freebsd/lib/libc/stdio/makebuf.c \ upstream-freebsd/lib/libc/stdio/mktemp.c \ - upstream-freebsd/lib/libc/stdio/setvbuf.c \ upstream-freebsd/lib/libc/stdlib/abs.c \ upstream-freebsd/lib/libc/stdlib/getopt_long.c \ upstream-freebsd/lib/libc/stdlib/imaxabs.c \ @@ -279,7 +276,6 @@ libc_upstream_netbsd_src_files := \ upstream-netbsd/lib/libc/stdlib/div.c \ upstream-netbsd/lib/libc/stdlib/drand48.c \ upstream-netbsd/lib/libc/stdlib/erand48.c \ - upstream-netbsd/lib/libc/stdlib/exit.c \ upstream-netbsd/lib/libc/stdlib/jrand48.c \ upstream-netbsd/lib/libc/stdlib/ldiv.c \ upstream-netbsd/lib/libc/stdlib/lldiv.c \ @@ -381,6 +377,7 @@ libc_upstream_openbsd_src_files := \ upstream-openbsd/lib/libc/stdio/fgetwc.c \ upstream-openbsd/lib/libc/stdio/fgetws.c \ upstream-openbsd/lib/libc/stdio/fileno.c \ + upstream-openbsd/lib/libc/stdio/findfp.c \ upstream-openbsd/lib/libc/stdio/fprintf.c \ upstream-openbsd/lib/libc/stdio/fpurge.c \ upstream-openbsd/lib/libc/stdio/fputc.c \ @@ -407,6 +404,7 @@ libc_upstream_openbsd_src_files := \ upstream-openbsd/lib/libc/stdio/gets.c \ upstream-openbsd/lib/libc/stdio/getwc.c \ upstream-openbsd/lib/libc/stdio/getwchar.c \ + upstream-openbsd/lib/libc/stdio/makebuf.c \ upstream-openbsd/lib/libc/stdio/perror.c \ upstream-openbsd/lib/libc/stdio/printf.c \ upstream-openbsd/lib/libc/stdio/putc.c \ @@ -422,6 +420,7 @@ libc_upstream_openbsd_src_files := \ upstream-openbsd/lib/libc/stdio/scanf.c \ upstream-openbsd/lib/libc/stdio/setbuf.c \ upstream-openbsd/lib/libc/stdio/setbuffer.c \ + upstream-openbsd/lib/libc/stdio/setvbuf.c \ upstream-openbsd/lib/libc/stdio/sscanf.c \ upstream-openbsd/lib/libc/stdio/stdio.c \ upstream-openbsd/lib/libc/stdio/swprintf.c \ @@ -451,6 +450,7 @@ libc_upstream_openbsd_src_files := \ upstream-openbsd/lib/libc/stdlib/atoi.c \ upstream-openbsd/lib/libc/stdlib/atol.c \ upstream-openbsd/lib/libc/stdlib/atoll.c \ + upstream-openbsd/lib/libc/stdlib/exit.c \ upstream-openbsd/lib/libc/stdlib/getenv.c \ upstream-openbsd/lib/libc/stdlib/setenv.c \ upstream-openbsd/lib/libc/stdlib/strtoimax.c \ diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp index 6fcdfdaf6..69ac0e503 100644 --- a/libc/bionic/abort.cpp +++ b/libc/bionic/abort.cpp @@ -32,8 +32,6 @@ #include #include "atexit.h" -__LIBC_HIDDEN__ void (*__cleanup)(); - #ifdef __arm__ extern "C" __LIBC_HIDDEN__ void __libc_android_abort() #else @@ -47,11 +45,6 @@ void abort() sigdelset(&mask, SIGABRT); sigprocmask(SIG_SETMASK, &mask, NULL); - // POSIX requires we flush stdio buffers on abort. - if (__cleanup) { - (*__cleanup)(); - } - raise(SIGABRT); // If SIGABRT ignored, or caught and the handler returns, diff --git a/libc/bionic/dlmalloc.c b/libc/bionic/dlmalloc.c index 66a825b33..3a615d2e6 100644 --- a/libc/bionic/dlmalloc.c +++ b/libc/bionic/dlmalloc.c @@ -34,10 +34,7 @@ static void* named_anonymous_mmap(size_t length); // Ugly inclusion of C file so that bionic specific #defines configure dlmalloc. #include "../upstream-dlmalloc/malloc.c" -extern void (*__cleanup)(); - static void __bionic_heap_corruption_error(const char* function) { - __cleanup = NULL; // The heap is corrupt. We can forget trying to shut down stdio. __libc_fatal("heap corruption detected by %s", function); } diff --git a/libc/stdlib/atexit.c b/libc/stdlib/atexit.c index b051e22d5..c6072069b 100644 --- a/libc/stdlib/atexit.c +++ b/libc/stdlib/atexit.c @@ -104,10 +104,10 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso) { struct atexit *p = __atexit; struct atexit_fn *fnp; - int pgsize = getpagesize(); + size_t pgsize = sysconf(_SC_PAGESIZE); int ret = -1; - if (pgsize < (int)sizeof(*p)) + if (pgsize < sizeof(*p)) return (-1); _ATEXIT_LOCK(); p = __atexit; @@ -216,3 +216,41 @@ __cxa_finalize(void *dso) } _ATEXIT_UNLOCK(); } + +/* + * Register the cleanup function + */ +void +__atexit_register_cleanup(void (*func)(void)) +{ + struct atexit *p; + size_t pgsize = sysconf(_SC_PAGESIZE); + + if (pgsize < sizeof(*p)) + return; + _ATEXIT_LOCK(); + p = __atexit; + while (p != NULL && p->next != NULL) + p = p->next; + if (p == NULL) { + p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE, + MAP_ANON | MAP_PRIVATE, -1, 0); + if (p == MAP_FAILED) + goto unlock; + p->ind = 1; + p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) / + sizeof(p->fns[0]); + p->next = NULL; + __atexit = p; + } else { + if (mprotect(p, pgsize, PROT_READ | PROT_WRITE)) + goto unlock; + } + p->fns[0].cxa_func = (void (*)(void*))func; + p->fns[0].fn_arg = NULL; + p->fns[0].fn_dso = NULL; + mprotect(p, pgsize, PROT_READ); +unlock: + _ATEXIT_UNLOCK(); +} + diff --git a/libc/stdio/findfp.c b/libc/upstream-openbsd/lib/libc/stdio/findfp.c similarity index 84% rename from libc/stdio/findfp.c rename to libc/upstream-openbsd/lib/libc/stdio/findfp.c index 2dd32c974..b8c7dc137 100644 --- a/libc/stdio/findfp.c +++ b/libc/upstream-openbsd/lib/libc/stdio/findfp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: findfp.c,v 1.9 2005/08/08 08:05:36 espie Exp $ */ +/* $OpenBSD: findfp.c,v 1.15 2013/12/17 16:33:27 deraadt Exp $ */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. @@ -54,7 +54,7 @@ int __sdidinit; /* p r w flags file _bf z cookie close read seek write ext */ -/* the usual - (stdin + stdout + stderr) */ + /* the usual - (stdin + stdout + stderr) */ static FILE usual[FOPEN_MAX - 3]; static struct __sfileext usualext[FOPEN_MAX - 3]; static struct glue uglue = { 0, FOPEN_MAX - 3, usual }; @@ -62,7 +62,6 @@ static struct glue *lastglue = &uglue; _THREAD_PRIVATE_MUTEX(__sfp_mutex); static struct __sfileext __sFext[3]; - FILE __sF[3] = { std(__SRD, STDIN_FILENO), /* stdin */ std(__SWR, STDOUT_FILENO), /* stdout */ @@ -144,35 +143,11 @@ found: return (fp); } -#if 0 -#define getdtablesize() sysconf(_SC_OPEN_MAX) - /* - * XXX. Force immediate allocation of internal memory. Not used by stdio, - * but documented historically for certain applications. Bad applications. - */ -void -f_prealloc(void) -{ - struct glue *g; - int n; - - n = getdtablesize() - FOPEN_MAX + 20; /* 20 for slop. */ - for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next) - /* void */; - if (n > 0 && ((g = moreglue(n)) != NULL)) { - _THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex); - lastglue->next = g; - lastglue = g; - _THREAD_PRIVATE_MUTEX_UNLOCK(__sfp_mutex); - } -} -#endif - -/* - * exit() calls _cleanup() through *__cleanup, set whenever we - * open or buffer a file. This chicanery is done so that programs - * that do not use stdio need not link it all in. + * exit() and abort() call _cleanup() through the callback registered + * with __atexit_register_cleanup(), set whenever we open or buffer a + * file. This chicanery is done so that programs that do not use stdio + * need not link it all in. * * The name `_cleanup' is, alas, fairly well known outside stdio. */ @@ -199,7 +174,7 @@ __sinit(void) _FILEEXT_SETUP(usual+i, usualext+i); } /* make sure we clean up on exit */ - __cleanup = _cleanup; /* conservative */ + __atexit_register_cleanup(_cleanup); /* conservative */ __sdidinit = 1; out: _THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex); diff --git a/libc/upstream-freebsd/lib/libc/stdio/makebuf.c b/libc/upstream-openbsd/lib/libc/stdio/makebuf.c similarity index 86% rename from libc/upstream-freebsd/lib/libc/stdio/makebuf.c rename to libc/upstream-openbsd/lib/libc/stdio/makebuf.c index a92087e0e..d47e27cf3 100644 --- a/libc/upstream-freebsd/lib/libc/stdio/makebuf.c +++ b/libc/upstream-openbsd/lib/libc/stdio/makebuf.c @@ -1,3 +1,4 @@ +/* $OpenBSD: makebuf.c,v 1.8 2005/12/28 18:50:22 millert Exp $ */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. @@ -30,21 +31,11 @@ * SUCH DAMAGE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ -#include -__FBSDID("$FreeBSD$"); - -#include "namespace.h" #include #include #include #include #include -#include "un-namespace.h" - -#include "libc_private.h" #include "local.h" /* @@ -52,7 +43,7 @@ __FBSDID("$FreeBSD$"); * Per the ANSI C standard, ALL tty devices default to line buffered. * * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek - * optimisation) right after the _fstat() that finds the buffer size. + * optimisation) right after the fstat() that finds the buffer size. */ void __smakebuf(FILE *fp) @@ -74,7 +65,7 @@ __smakebuf(FILE *fp) fp->_bf._size = 1; return; } - __cleanup = _cleanup; + __atexit_register_cleanup(_cleanup); flags |= __SMBF; fp->_bf._base = fp->_p = p; fp->_bf._size = size; @@ -91,15 +82,15 @@ __swhatbuf(FILE *fp, size_t *bufsize, int *couldbetty) { struct stat st; - if (fp->_file < 0 || _fstat(fp->_file, &st) < 0) { + if (fp->_file < 0 || fstat(fp->_file, &st) < 0) { *couldbetty = 0; *bufsize = BUFSIZ; return (__SNPT); } /* could be a tty iff it is a character device */ - *couldbetty = (st.st_mode & S_IFMT) == S_IFCHR; - if (st.st_blksize <= 0) { + *couldbetty = S_ISCHR(st.st_mode); + if (st.st_blksize == 0) { *bufsize = BUFSIZ; return (__SNPT); } diff --git a/libc/upstream-freebsd/lib/libc/stdio/setvbuf.c b/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c similarity index 90% rename from libc/upstream-freebsd/lib/libc/stdio/setvbuf.c rename to libc/upstream-openbsd/lib/libc/stdio/setvbuf.c index d39696058..6c49f7a5d 100644 --- a/libc/upstream-freebsd/lib/libc/stdio/setvbuf.c +++ b/libc/upstream-openbsd/lib/libc/stdio/setvbuf.c @@ -1,3 +1,4 @@ +/* $OpenBSD: setvbuf.c,v 1.11 2009/11/09 00:18:27 kurt Exp $ */ /*- * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. @@ -30,25 +31,16 @@ * SUCH DAMAGE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)setvbuf.c 8.2 (Berkeley) 11/16/93"; -#endif /* LIBC_SCCS and not lint */ -#include -__FBSDID("$FreeBSD$"); - -#include "namespace.h" #include #include -#include "un-namespace.h" #include "local.h" -#include "libc_private.h" /* * Set one of the three kinds of buffering, optionally including * a buffer. */ int -setvbuf(FILE * __restrict fp, char * __restrict buf, int mode, size_t size) +setvbuf(FILE *fp, char *buf, int mode, size_t size) { int ret, flags; size_t iosize; @@ -63,22 +55,23 @@ setvbuf(FILE * __restrict fp, char * __restrict buf, int mode, size_t size) if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0) return (EOF); - FLOCKFILE(fp); /* * Write current buffer, if any. Discard unread input (including * ungetc data), cancel line buffering, and free old buffer if * malloc()ed. We also clear any eof condition, as if this were * a seek. */ + FLOCKFILE(fp); ret = 0; (void)__sflush(fp); if (HASUB(fp)) FREEUB(fp); + WCIO_FREE(fp); fp->_r = fp->_lbfsize = 0; flags = fp->_flags; if (flags & __SMBF) free((void *)fp->_bf._base); - flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SOFF | __SNPT | __SEOF); + flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SNPT | __SEOF); /* If setting unbuffered mode, skip all the hard work. */ if (mode == _IONBF) @@ -154,8 +147,8 @@ nbf: /* begin/continue reading, or stay in intermediate state */ fp->_w = 0; } - __cleanup = _cleanup; - FUNLOCKFILE(fp); + __atexit_register_cleanup(_cleanup); + return (ret); } diff --git a/libc/upstream-netbsd/lib/libc/stdlib/exit.c b/libc/upstream-openbsd/lib/libc/stdlib/exit.c similarity index 76% rename from libc/upstream-netbsd/lib/libc/stdlib/exit.c rename to libc/upstream-openbsd/lib/libc/stdlib/exit.c index 67e6adf1b..ef8b335c8 100644 --- a/libc/upstream-netbsd/lib/libc/stdlib/exit.c +++ b/libc/upstream-openbsd/lib/libc/stdlib/exit.c @@ -1,8 +1,7 @@ -/* $NetBSD: exit.c,v 1.15 2011/05/18 19:36:36 dsl Exp $ */ - +/* $OpenBSD: exit.c,v 1.12 2007/09/03 14:40:16 millert Exp $ */ /*- - * Copyright (c) 1990, 1993 - * The Regents of the University of California. All rights reserved. + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,23 +28,11 @@ * SUCH DAMAGE. */ -#include -#if defined(LIBC_SCCS) && !defined(lint) -#if 0 -static char sccsid[] = "@(#)exit.c 8.1 (Berkeley) 6/4/93"; -#else -__RCSID("$NetBSD: exit.c,v 1.15 2011/05/18 19:36:36 dsl Exp $"); -#endif -#endif /* LIBC_SCCS and not lint */ - +#include +#include #include #include -#ifdef _LIBC -#include "reentrant.h" #include "atexit.h" -#endif - -void (*__cleanup)(void); /* * Exit, flushing stdio buffers if necessary. @@ -53,11 +40,10 @@ void (*__cleanup)(void); void exit(int status) { - -#ifdef _LIBC + /* + * Call functions registered by atexit() or _cxa_atexit() + * (including the stdio cleanup routine) and then _exit(). + */ __cxa_finalize(NULL); -#endif - if (__cleanup) - (*__cleanup)(); _exit(status); }