OSDN Git Service

* dcrt0.cc (atexit_lock): Delete.
authorcgf <cgf>
Tue, 2 Feb 2010 02:00:01 +0000 (02:00 +0000)
committercgf <cgf>
Tue, 2 Feb 2010 02:00:01 +0000 (02:00 +0000)
(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.

winsup/cygwin/ChangeLog
winsup/cygwin/dcrt0.cc
winsup/cygwin/dll_init.cc
winsup/cygwin/dll_init.h
winsup/cygwin/init.cc

index f49a31c..5246135 100644 (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.
index f1f904a..7cd383b 100644 (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);
 }
 
index 763964b..e449f77 100644 (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)
-    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);
index 90cfa03..b37406e 100644 (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*);
index efdd775..9bf49f2 100644 (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