This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]