* dcrt0.cc (atexit_lock): Delete.

(cygwin_exit): Remove atexit lock.
(cygwin_atexit): Ditto.  Rename parameter to match newlib.  Call __cxa_atexit
when invoked by a registered DLL.
* dll_init.cc (remove_dll_atexit): Delete.
(dll_list::find): New function.
(dll_list::detach): Use dll_list::find to find dll associated with return
address.  Use __cxa_finalize to run atexit functions associated with the dll.
(cygwin_detach_dll): Don't assume that HANDLE == void *.
* dll_init.h (dll_list::find): Declare.
(__cxa_atexit): Ditto.
(__cxa_finalize): Ditto.
* init.cc (dll_entry): Clarify comment.
This commit is contained in:
Christopher Faylor
2010-02-02 02:00:01 +00:00
parent a390615010
commit fc6a0dc849
5 changed files with 58 additions and 60 deletions

View File

@ -143,63 +143,43 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
return d;
}
/* This function looks for every atexit function registered in the
about-to-be-unloaded DLL and runs it.
newlib does not provide any method for selectively running elements
from the atexit() queue so we have to roll our own.
Note that this is not foolproof since a function in the DLL could
register an atexit function outside of the DLL and that should be
run when the DLL detachs. */
static void
remove_dll_atexit (MEMORY_BASIC_INFORMATION& m)
dll *
dll_list::find (void *retaddr)
{
unsigned char *dll_beg = (unsigned char *) m.AllocationBase;
unsigned char *dll_end = (unsigned char *) m.AllocationBase + m.RegionSize;
struct _atexit *p = _GLOBAL_REENT->_atexit;
for (int n = p->_ind - 1; n >= 0; n--)
{
void (*fn) (void) = p->_fns[n];
if ((unsigned char *) fn >= dll_beg && (unsigned char *) fn < dll_end)
{
fn ();
p->_fns[n] = NULL;
}
}
MEMORY_BASIC_INFORMATION m;
if (!VirtualQuery (retaddr, &m, sizeof m))
return NULL;
HMODULE h = (HMODULE) m.AllocationBase;
dll *d = &start;
while ((d = d->next))
if (d->handle == h)
break;
return d;
}
/* Detach a DLL from the chain. */
void
dll_list::detach (void *retaddr)
{
if (!myself || exit_state)
dll *d;
if (!myself || exit_state || !(d = find (retaddr)))
return;
MEMORY_BASIC_INFORMATION m;
if (!VirtualQuery (retaddr, &m, sizeof m))
return;
HMODULE h = (HMODULE) m.AllocationBase;
dll *d = &start;
while ((d = d->next))
if (d->handle != h)
continue;
else if (d->count <= 0)
system_printf ("WARNING: trying to detach an already detached dll ...");
else if (--d->count == 0)
{
remove_dll_atexit (m);
d->run_dtors ();
d->prev->next = d->next;
if (d->next)
d->next->prev = d->prev;
if (d->type == DLL_LOAD)
loaded_dlls--;
if (end == d)
end = d->prev;
cfree (d);
break;
}
if (d->count <= 0)
system_printf ("WARNING: trying to detach an already detached dll ...");
if (--d->count == 0)
{
__cxa_finalize (d);
d->run_dtors ();
d->prev->next = d->next;
if (d->next)
d->next->prev = d->prev;
if (d->type == DLL_LOAD)
loaded_dlls--;
if (end == d)
end = d->prev;
cfree (d);
}
}
/* Initialization for all linked DLLs, called by dll_crt0_1. */
@ -427,7 +407,7 @@ cygwin_detach_dll (dll *)
{
HANDLE retaddr;
if (_my_tls.isinitialized ())
retaddr = (HANDLE) _my_tls.retaddr ();
retaddr = (void *) _my_tls.retaddr ();
else
retaddr = __builtin_return_address (0);
dlls.detach (retaddr);