mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-19 04:49:25 +08:00
* 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>
|
||||
|
||||
* how-startup-shutdown-works.txt: Add new document.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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*);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user