* 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

@ -1,3 +1,21 @@
2010-02-01 Christopher Faylor <me+cygwin@cgf.cx>
* 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.
2010-02-02 Dave Korn <dave.korn.cygwin@gmail.com>
* how-startup-shutdown-works.txt: Add new document.

View File

@ -1108,24 +1108,18 @@ do_exit (int status)
myself.exit (n);
}
static NO_COPY muto atexit_lock;
extern "C" int
cygwin_atexit (void (*function)(void))
cygwin_atexit (void (*fn) (void))
{
int res;
atexit_lock.init ("atexit_lock");
atexit_lock.acquire ();
res = atexit (function);
atexit_lock.release ();
dll *d = dlls.find ((void *) _my_tls.retaddr ());
res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
return res;
}
extern "C" void
cygwin_exit (int n)
{
if (atexit_lock)
atexit_lock.acquire ();
exit (n);
}

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);

View File

@ -79,6 +79,7 @@ public:
int reload_on_fork;
dll *operator [] (const PWCHAR name);
dll *alloc (HINSTANCE, per_process *, dll_type);
dll *find (void *);
void detach (void *);
void init ();
void load_after_fork (HANDLE);
@ -100,3 +101,8 @@ public:
extern dll_list dlls;
void dll_global_dtors ();
/* These probably belong in a newlib header but we can keep them here
for now. */
extern "C" int __cxa_atexit(void (*)(void*), void*, void*);
extern "C" int __cxa_finalize(void*);

View File

@ -126,7 +126,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
cygwin_hmodule = (HMODULE) h;
dynamically_loaded = (static_load == NULL);
/* Is the stack at an unusual address? This is, an address which
/* Is the stack at an unusual address? That is, an address which
is in the usual space occupied by the process image, but below
the auto load address of DLLs?
Check if we're running in WOW64 on a 64 bit machine *and* are