This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
[patch] __call_atexit.c: Fix __call_exitprocs.
- From: Kazu Hirata <kazu at codesourcery dot com>
- To: newlib at sources dot redhat dot com
- Cc: mark at codesourcery dot com
- Date: Thu, 5 Apr 2007 06:30:30 -0700
- Subject: [patch] __call_atexit.c: Fix __call_exitprocs.
Hi,
Attached is a patch to fix __call_exitprocs, which in turn fixes
failures of g++.old-deja/g++.other/init18.C and
g++.old-deja/g++.other/init19.C in the g++ testsuite.
Here is a description from Mark Mitchell.
The init19.C failures we're seeing with GCC 4.2 on newlib targets
are in fact a bug in newlib. The test case is calling "atexit" from
within a function that is itself an "atexit" function; in other
words, we call exit, which calls the first atexit function, which
then registers a second atexit function. The second atexit function
was never being called by newlib. The C99 standard does imply that
the library should handle this case:
First, all functions registered by the atexit function are called,
in the reverse order of their registration, except that a function
is called after any previously registered functions that had been
called at the time it was registered.
That last clause says that the second atexit function above is
called after the first one, even though the first one was registered
first.
Tested on fido-none-elf and m68k-elf. OK to apply?
Kazu Hirata
newlib/
2007-04-04 Mark Mitchell <mark@codesourcery.com>
* libc/stdlib/__call_atexit.c (__call_exitprocs): Handle atexit
functions registering additional atexit functions.
Index: newlib/libc/stdlib/__call_atexit.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdlib/__call_atexit.c,v
retrieving revision 1.4
diff -u -d -p -r1.4 __call_atexit.c
--- newlib/libc/stdlib/__call_atexit.c 21 Mar 2006 00:57:34 -0000 1.4
+++ newlib/libc/stdlib/__call_atexit.c 5 Apr 2007 03:17:23 -0000
@@ -23,6 +23,8 @@ _DEFUN (__call_exitprocs, (code, d),
int i;
void (*fn) (void);
+ restart:
+
p = _GLOBAL_REENT->_atexit;
lastp = &_GLOBAL_REENT->_atexit;
while (p)
@@ -34,6 +36,8 @@ _DEFUN (__call_exitprocs, (code, d),
#endif
for (n = p->_ind - 1; n >= 0; n--)
{
+ int ind;
+
i = 1 << n;
/* Skip functions not from this dso. */
@@ -52,6 +56,8 @@ _DEFUN (__call_exitprocs, (code, d),
if (!fn)
continue;
+ ind = p->_ind;
+
/* Call the function. */
if (!args || (args->_fntypes & i) == 0)
fn ();
@@ -59,6 +65,12 @@ _DEFUN (__call_exitprocs, (code, d),
(*((void (*)(int, _PTR)) fn))(code, args->_fnargs[n]);
else
(*((void (*)(_PTR)) fn))(args->_fnargs[n]);
+
+ /* The function we called called atexit and registered another
+ function (or functions). Call these new functions before
+ continuing with the already registered fucntions. */
+ if (ind != p->_ind || *lastp != p)
+ goto restart;
}
#ifndef _ATEXIT_DYNAMIC_ALLOC