* 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:
parent
a390615010
commit
fc6a0dc849
|
@ -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>
|
2010-02-02 Dave Korn <dave.korn.cygwin@gmail.com>
|
||||||
|
|
||||||
* how-startup-shutdown-works.txt: Add new document.
|
* how-startup-shutdown-works.txt: Add new document.
|
||||||
|
|
|
@ -1108,24 +1108,18 @@ do_exit (int status)
|
||||||
myself.exit (n);
|
myself.exit (n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static NO_COPY muto atexit_lock;
|
|
||||||
|
|
||||||
extern "C" int
|
extern "C" int
|
||||||
cygwin_atexit (void (*function)(void))
|
cygwin_atexit (void (*fn) (void))
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
atexit_lock.init ("atexit_lock");
|
dll *d = dlls.find ((void *) _my_tls.retaddr ());
|
||||||
atexit_lock.acquire ();
|
res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
|
||||||
res = atexit (function);
|
|
||||||
atexit_lock.release ();
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
cygwin_exit (int n)
|
cygwin_exit (int n)
|
||||||
{
|
{
|
||||||
if (atexit_lock)
|
|
||||||
atexit_lock.acquire ();
|
|
||||||
exit (n);
|
exit (n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,63 +143,43 @@ dll_list::alloc (HINSTANCE h, per_process *p, dll_type type)
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function looks for every atexit function registered in the
|
dll *
|
||||||
about-to-be-unloaded DLL and runs it.
|
dll_list::find (void *retaddr)
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
unsigned char *dll_beg = (unsigned char *) m.AllocationBase;
|
MEMORY_BASIC_INFORMATION m;
|
||||||
unsigned char *dll_end = (unsigned char *) m.AllocationBase + m.RegionSize;
|
if (!VirtualQuery (retaddr, &m, sizeof m))
|
||||||
struct _atexit *p = _GLOBAL_REENT->_atexit;
|
return NULL;
|
||||||
for (int n = p->_ind - 1; n >= 0; n--)
|
HMODULE h = (HMODULE) m.AllocationBase;
|
||||||
{
|
|
||||||
void (*fn) (void) = p->_fns[n];
|
dll *d = &start;
|
||||||
if ((unsigned char *) fn >= dll_beg && (unsigned char *) fn < dll_end)
|
while ((d = d->next))
|
||||||
{
|
if (d->handle == h)
|
||||||
fn ();
|
break;
|
||||||
p->_fns[n] = NULL;
|
return d;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Detach a DLL from the chain. */
|
/* Detach a DLL from the chain. */
|
||||||
void
|
void
|
||||||
dll_list::detach (void *retaddr)
|
dll_list::detach (void *retaddr)
|
||||||
{
|
{
|
||||||
if (!myself || exit_state)
|
dll *d;
|
||||||
|
if (!myself || exit_state || !(d = find (retaddr)))
|
||||||
return;
|
return;
|
||||||
MEMORY_BASIC_INFORMATION m;
|
if (d->count <= 0)
|
||||||
if (!VirtualQuery (retaddr, &m, sizeof m))
|
system_printf ("WARNING: trying to detach an already detached dll ...");
|
||||||
return;
|
if (--d->count == 0)
|
||||||
HMODULE h = (HMODULE) m.AllocationBase;
|
{
|
||||||
|
__cxa_finalize (d);
|
||||||
dll *d = &start;
|
d->run_dtors ();
|
||||||
while ((d = d->next))
|
d->prev->next = d->next;
|
||||||
if (d->handle != h)
|
if (d->next)
|
||||||
continue;
|
d->next->prev = d->prev;
|
||||||
else if (d->count <= 0)
|
if (d->type == DLL_LOAD)
|
||||||
system_printf ("WARNING: trying to detach an already detached dll ...");
|
loaded_dlls--;
|
||||||
else if (--d->count == 0)
|
if (end == d)
|
||||||
{
|
end = d->prev;
|
||||||
remove_dll_atexit (m);
|
cfree (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);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialization for all linked DLLs, called by dll_crt0_1. */
|
/* Initialization for all linked DLLs, called by dll_crt0_1. */
|
||||||
|
@ -427,7 +407,7 @@ cygwin_detach_dll (dll *)
|
||||||
{
|
{
|
||||||
HANDLE retaddr;
|
HANDLE retaddr;
|
||||||
if (_my_tls.isinitialized ())
|
if (_my_tls.isinitialized ())
|
||||||
retaddr = (HANDLE) _my_tls.retaddr ();
|
retaddr = (void *) _my_tls.retaddr ();
|
||||||
else
|
else
|
||||||
retaddr = __builtin_return_address (0);
|
retaddr = __builtin_return_address (0);
|
||||||
dlls.detach (retaddr);
|
dlls.detach (retaddr);
|
||||||
|
|
|
@ -79,6 +79,7 @@ public:
|
||||||
int reload_on_fork;
|
int reload_on_fork;
|
||||||
dll *operator [] (const PWCHAR name);
|
dll *operator [] (const PWCHAR name);
|
||||||
dll *alloc (HINSTANCE, per_process *, dll_type);
|
dll *alloc (HINSTANCE, per_process *, dll_type);
|
||||||
|
dll *find (void *);
|
||||||
void detach (void *);
|
void detach (void *);
|
||||||
void init ();
|
void init ();
|
||||||
void load_after_fork (HANDLE);
|
void load_after_fork (HANDLE);
|
||||||
|
@ -100,3 +101,8 @@ public:
|
||||||
|
|
||||||
extern dll_list dlls;
|
extern dll_list dlls;
|
||||||
void dll_global_dtors ();
|
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*);
|
||||||
|
|
|
@ -126,7 +126,7 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
|
||||||
cygwin_hmodule = (HMODULE) h;
|
cygwin_hmodule = (HMODULE) h;
|
||||||
dynamically_loaded = (static_load == NULL);
|
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
|
is in the usual space occupied by the process image, but below
|
||||||
the auto load address of DLLs?
|
the auto load address of DLLs?
|
||||||
Check if we're running in WOW64 on a 64 bit machine *and* are
|
Check if we're running in WOW64 on a 64 bit machine *and* are
|
||||||
|
|
Loading…
Reference in New Issue