* 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:
@ -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);
|
||||
|
Reference in New Issue
Block a user