summaryrefslogtreecommitdiffstats
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
parenta3906150100103ab8e268f9ad0785fca83341e9f (diff)
downloadcygnal-fc6a0dc849d07c3aace5e06fa6eee01b45e83d68.tar.gz
cygnal-fc6a0dc849d07c3aace5e06fa6eee01b45e83d68.tar.bz2
cygnal-fc6a0dc849d07c3aace5e06fa6eee01b45e83d68.zip
* 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.
-rw-r--r--winsup/cygwin/ChangeLog18
-rw-r--r--winsup/cygwin/dcrt0.cc12
-rw-r--r--winsup/cygwin/dll_init.cc80
-rw-r--r--winsup/cygwin/dll_init.h6
-rw-r--r--winsup/cygwin/init.cc2
5 files changed, 58 insertions, 60 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index f49a31c8e..5246135e1 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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.
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index f1f904ac7..7cd383bf7 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -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);
}
diff --git a/winsup/cygwin/dll_init.cc b/winsup/cygwin/dll_init.cc
index 763964bac..e449f7777 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);
diff --git a/winsup/cygwin/dll_init.h b/winsup/cygwin/dll_init.h
index 90cfa03e2..b37406e82 100644
--- a/winsup/cygwin/dll_init.h
+++ b/winsup/cygwin/dll_init.h
@@ -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*);
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc
index efdd775c4..9bf49f2a3 100644
--- a/winsup/cygwin/init.cc
+++ b/winsup/cygwin/init.cc
@@ -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