mailing list of musl libc
 help / color / mirror / code / Atom feed
* Timing of destructors?
@ 2012-06-14 11:01 Richard Pennington
  2012-06-14 12:32 ` Szabolcs Nagy
  0 siblings, 1 reply; 3+ messages in thread
From: Richard Pennington @ 2012-06-14 11:01 UTC (permalink / raw)
  To: musl

Hi,

I have a small test program:
#include <stdio.h>
#include <stdlib.h>

void before(void) __attribute__((constructor));
void before(void)
{
    printf("before\n");
}

void after(void) __attribute__((destructor));
void after(void)
{
    printf("after\n");
}

int main()
{
    printf("hello world\n");
}

which doesn't print "after". This is because stdio is cleaned up before 
destructors are called in exit.c. Using stdio in destructors can be handy for 
debugging (if nothing else). Would it be evil to modify exit.c to look like 
this?:

void exit(int code)
{
        static int lock;

        /* If more than one thread calls exit, hang until _Exit ends it all */
        while (a_swap(&lock, 1)) __syscall(SYS_pause);

        /* Destructor s**t is kept separate from atexit to avoid bloat */
        if (libc.fini) libc.fini();
        if (libc.ldso_fini) libc.ldso_fini();

        /* Only do atexit & stdio flush if they were actually used */
        __funcs_on_exit();
        __fflush_on_exit();

        _Exit(code);
        for(;;);
}

The change is to move the *_on_exit() calls to after the destructors have been 
called.

-Rich


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Timing of destructors?
  2012-06-14 11:01 Timing of destructors? Richard Pennington
@ 2012-06-14 12:32 ` Szabolcs Nagy
  2012-06-14 12:35   ` Rich Felker
  0 siblings, 1 reply; 3+ messages in thread
From: Szabolcs Nagy @ 2012-06-14 12:32 UTC (permalink / raw)
  To: musl

* Richard Pennington <rich@pennware.com> [2012-06-14 06:01:45 -0500]:
> which doesn't print "after". This is because stdio is cleaned up before 
> destructors are called in exit.c. Using stdio in destructors can be handy for 
> debugging (if nothing else). Would it be evil to modify exit.c to look like 
> this?:
> 
> void exit(int code)
> {
>         static int lock;
> 
>         /* If more than one thread calls exit, hang until _Exit ends it all */
>         while (a_swap(&lock, 1)) __syscall(SYS_pause);
> 
>         /* Destructor s**t is kept separate from atexit to avoid bloat */
>         if (libc.fini) libc.fini();
>         if (libc.ldso_fini) libc.ldso_fini();
> 
>         /* Only do atexit & stdio flush if they were actually used */
>         __funcs_on_exit();
>         __fflush_on_exit();
> 
>         _Exit(code);
>         for(;;);
> }
> 
> The change is to move the *_on_exit() calls to after the destructors have been 
> called.
> 

the c standard does not say anything about destructors
(obviously) otherwise the cleanup order is atexit handlers
then stdio cleanups.

c++ specifies that destructors come before stdio cleanups
(interleaved with atexit handlers based on the execution order
of the constructor and atexit call)

more precisely c++11 "18.5 Start and termination":

"The function exit() has additional behavior in this International Standard:
-- First, objects with thread storage duration and associated with the current thread are destroyed.
   Next, objects with static storage duration are destroyed and functions registered by calling atexit
   are called. See 3.6.3 for the order of destructions and calls. (Automatic objects are not
   destroyed as a result of calling exit().)
   If control leaves a registered function called by exit because the function does not provide a
   handler for a thrown exception, terminate() shall be called (15.5.1).
-- Next, all open C streams (as mediated by the function signatures declared in <cstdio>) with
   unwritten buffered data are flushed, all open C streams are closed, and all files created by calling
   tmpfile() are removed.
-- Finally, control is returned to the host environment. If status is zero or EXIT_SUCCESS, an
   implementation-defined form of the status successful termination is returned. If status is EXIT_-
   FAILURE, an implementation-defined form of the status unsuccessful termination is returned.
   Otherwise the status returned is implementation-defined."


of course gcc destructor attribute is not the same as c++
destructors of static duration objects but i'd expect them
to behave the same way ie. come before __fflush_on_exit();

i'm not sure about __funcs_on_exit() and destructor order,
i think destructors should come later as they are 'registered'
earlier than the atexit handlers

so i think the most correct is

/* Only do atexit if they were actually used */
__funcs_on_exit();
/* Destructor s**t is kept separate from atexit to avoid bloat */
if (libc.fini) libc.fini();
if (libc.ldso_fini) libc.ldso_fini();
/* Only do stdio flush if they were actually used */
__fflush_on_exit();
_Exit(code);


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Timing of destructors?
  2012-06-14 12:32 ` Szabolcs Nagy
@ 2012-06-14 12:35   ` Rich Felker
  0 siblings, 0 replies; 3+ messages in thread
From: Rich Felker @ 2012-06-14 12:35 UTC (permalink / raw)
  To: musl

On Thu, Jun 14, 2012 at 02:32:47PM +0200, Szabolcs Nagy wrote:
> * Richard Pennington <rich@pennware.com> [2012-06-14 06:01:45 -0500]:
> > which doesn't print "after". This is because stdio is cleaned up before 
> > destructors are called in exit.c. Using stdio in destructors can be handy for 
> > debugging (if nothing else). Would it be evil to modify exit.c to look like 
> > this?:
> > [...]

Yes.

> so i think the most correct is
> 
> /* Only do atexit if they were actually used */
> __funcs_on_exit();
> /* Destructor s**t is kept separate from atexit to avoid bloat */
> if (libc.fini) libc.fini();
> if (libc.ldso_fini) libc.ldso_fini();
> /* Only do stdio flush if they were actually used */
> __fflush_on_exit();
> _Exit(code);

Making the change. And I'll just remove the comment. It was left
behind from an old version of the code that used function pointers and
if(ptr) to make the call. Since it was switched to use weak symbols,
the motivation for the comment seems to have been lost.

Rich


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2012-06-14 12:35 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-14 11:01 Timing of destructors? Richard Pennington
2012-06-14 12:32 ` Szabolcs Nagy
2012-06-14 12:35   ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).