* 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).