aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/dll_init.cc
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2010-02-02 02:00:01 +0000
committerChristopher Faylor <me@cgf.cx>2010-02-02 02:00:01 +0000
commitfc6a0dc849d07c3aace5e06fa6eee01b45e83d68 (patch)
treedac1dd4b9a2ec218156b50c57db3753c58c81413 /winsup/cygwin/dll_init.cc
parenta3906150100103ab8e268f9ad0785fca83341e9f (diff)
downloadnewlib-fc6a0dc849d07c3aace5e06fa6eee01b45e83d68.zip
newlib-fc6a0dc849d07c3aace5e06fa6eee01b45e83d68.tar.gz
newlib-fc6a0dc849d07c3aace5e06fa6eee01b45e83d68.tar.bz2
* 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.
Diffstat (limited to 'winsup/cygwin/dll_init.cc')
-rw-r--r--winsup/cygwin/dll_init.cc80
1 files changed, 30 insertions, 50 deletions
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc
index 763964b..e449f77 100644
--- a/winsup/cygwin/dll_init.cc
+++ b/winsup/cygwin/dll_init.cc
@@ -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)
- return;
- MEMORY_BASIC_INFORMATION m;
- if (!VirtualQuery (retaddr, &m, sizeof m))
+ dll *d;
+ if (!myself || exit_state || !(d = find (retaddr)))
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);