This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: p2736.C Is dtor order guaranteed?
- To: hjl at lucon dot org (H.J. Lu)
- Subject: Re: p2736.C Is dtor order guaranteed?
- From: Ulrich Drepper <drepper at cygnus dot com>
- Date: 22 Jul 1998 16:03:26 -0700
- Cc: martin at mira dot isdn dot cs dot tu-berlin dot de (Martin von Loewis), jason at cygnus dot com, egcs at cygnus dot com
- References: <m0yz7Uk-00038iC@ocean.lucon.org>
- Reply-To: drepper at cygnus dot com (Ulrich Drepper)
hjl@lucon.org (H.J. Lu) writes:
> I believe Linux has no such restriction.
Yes.
> However, I'd like to revert back to __DTOR_LIST__ if a shared
> library is loaded via dlopen.
Excuse my ignorance but I haven't followed this thread. Why is on
Linux anything different than __DTOR_LIST__ in use?
> Otherwise, we will get a core dump after dlclose when the program
> exits. We can put a restriction on dlopened objects that they cannot
> call atexit explicitly or implicitly in C or C++.
This restriction always exists if the function to be started is in the
dynamically loaded object.
> Ulrich, can we expend the dynamic linker in glibc to let the shared
> library know if it is loaded via dlopen? If we can do that, the change
> to egcs will be simple:
>
> static func_ptr __CTOR_END__[];
> static func_ptr __DTOR_END__[];
> static void
> __do_global_ctors_aux ()
> {
> func_ptr *p;
> if (dlopened)
> for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
> (*p) ();
> else
> {
> func_ptr *dp = __CTOR_END__ - 1;
I assume you means __DTOR_END__ ^^^ here.
> for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--, dp--)
> {
> (*p) ();
> atexit (dp);
> }
> *(dp + 1) = NULL;
> }
> }
I think the code should look like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static func_ptr __CTOR_END__[];
static func_ptr __DTOR_END__[];
static int last_initialized;
static void
__do_global_ctors_aux ()
{
func_ptr *p;
for (p = __CTOR_END__ - 1; *p != (func_ptr) -1; p--)
{
(*p) ();
++last_initialized;
}
}
static void
__do_global_dtors_aux ()
{
func_ptr *p = __DTOR_END__ - last_initialized;
while (last_initialized > 0)
{
(*p) ();
--last_initialized;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Since the initialization code wil never be run by two threads at the
same time (the dynamic loader has to make this sure) there is no
problem with using a global variable.
This approach is faster (calling atexit is not cheap when done very
often) and this code also will call the destructors if the dynamically
loaded object is unloaded before the program ends.
This is similar to the code currently in crtstuff.c with the exception
that last_initialized is shared between the ctor and dtor which makes
all the difference.
--
---------------. drepper at gnu.org ,-. 1325 Chesapeake Terrace
Ulrich Drepper \ ,-------------------' \ Sunnyvale, CA 94089 USA
Cygnus Solutions `--' drepper at cygnus.com `------------------------