Bug 658995 part 2 - Use static destructors instead of atexit(). r=bsmedberg
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 15 Jun 2011 07:32:03 +0200
changeset 71497 f4ddad2c0eb7d079abeba227758176ba4992f59e
parent 71496 eef5d644e17e778357ab31306136dc88fc52413c
child 71498 8ae2a073b044817811fb8766929ef16074577445
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg
bugs658995
milestone7.0a1
Bug 658995 part 2 - Use static destructors instead of atexit(). r=bsmedberg
netwerk/base/src/nsStandardURL.cpp
profile/dirserviceprovider/src/nsProfileLock.cpp
profile/dirserviceprovider/src/nsProfileLock.h
tools/trace-malloc/lib/nsTraceMalloc.c
tools/trace-malloc/lib/nsTypeInfo.cpp
--- a/netwerk/base/src/nsStandardURL.cpp
+++ b/netwerk/base/src/nsStandardURL.cpp
@@ -320,17 +320,22 @@ nsStandardURL::~nsStandardURL()
 
     CRTFREEIF(mHostA);
 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
     PR_REMOVE_LINK(&mDebugCList);
 #endif
 }
 
 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
-static void DumpLeakedURLs()
+struct DumpLeakedURLs {
+    DumpLeakedURLs() {}
+    ~DumpLeakedURLs();
+};
+
+DumpLeakedURLs::~DumpLeakedURLs()
 {
     if (!PR_CLIST_IS_EMPTY(&gAllURLs)) {
         printf("Leaked URLs:\n");
         for (PRCList *l = PR_LIST_HEAD(&gAllURLs); l != &gAllURLs; l = PR_NEXT_LINK(l)) {
             nsStandardURL *url = reinterpret_cast<nsStandardURL*>(reinterpret_cast<char*>(l) - offsetof(nsStandardURL, mDebugCList));
             url->PrintSpec();
         }
     }
@@ -358,18 +363,22 @@ nsStandardURL::InitGlobalObjects()
 
 void
 nsStandardURL::ShutdownGlobalObjects()
 {
     NS_IF_RELEASE(gIDN);
     NS_IF_RELEASE(gCharsetMgr);
 
 #ifdef DEBUG_DUMP_URLS_AT_SHUTDOWN
-    if (gInitialized)
-        atexit(DumpLeakedURLs);
+    if (gInitialized) {
+        // This instanciates a dummy class, and will trigger the class
+        // destructor when libxul is unloaded. This is equivalent to atexit(),
+        // but gracefully handles dlclose().
+        static DumpLeakedURLs d;
+    }
 #endif
 }
 
 //----------------------------------------------------------------------------
 // nsStandardURL <private>
 //----------------------------------------------------------------------------
 
 void
--- a/profile/dirserviceprovider/src/nsProfileLock.cpp
+++ b/profile/dirserviceprovider/src/nsProfileLock.cpp
@@ -385,17 +385,20 @@ nsresult nsProfileLock::LockWithSymlink(
         mHaveLock = PR_TRUE;
         mPidLockFileName = strdup(fileName);
         if (mPidLockFileName)
         {
             PR_APPEND_LINK(this, &mPidLockList);
             if (!setupPidLockCleanup++)
             {
                 // Clean up on normal termination.
-                atexit(RemovePidLockFilesExiting);
+                // This instanciates a dummy class, and will trigger the class
+                // destructor when libxul is unloaded. This is equivalent to atexit(),
+                // but gracefully handles dlclose().
+                static RemovePidLockFilesExiting r;
 
                 // Clean up on abnormal termination, using POSIX sigaction.
                 // Don't arm a handler if the signal is being ignored, e.g.,
                 // because mozilla is run via nohup.
                 if (!sDisableSignalHandling) {
                     struct sigaction act, oldact;
 #ifdef SA_SIGINFO
                     act.sa_sigaction = FatalSignalHandler;
--- a/profile/dirserviceprovider/src/nsProfileLock.h
+++ b/profile/dirserviceprovider/src/nsProfileLock.h
@@ -94,24 +94,22 @@ private:
     PRPackedBool            mHaveLock;
 
 #if defined (XP_WIN)
     HANDLE                  mLockFileHandle;
 #elif defined (XP_OS2)
     LHANDLE                 mLockFileHandle;
 #elif defined (XP_UNIX)
 
-    static void             RemovePidLockFilesExiting()
-    {
-      // We can't implement this function with a default parameter on
-      // RemovePidLockFiles(aFatalSignal) since we register
-      //    atexit(RemovePidLockFilesExiting).
-
-      RemovePidLockFiles(PR_FALSE);
-    }
+    struct RemovePidLockFilesExiting {
+        RemovePidLockFilesExiting() {}
+        ~RemovePidLockFilesExiting() {
+            RemovePidLockFiles(PR_FALSE);
+        }
+    };
 
     static void             RemovePidLockFiles(PRBool aFatalSignal);
     static void             FatalSignalHandler(int signo
 #ifdef SA_SIGINFO
                                                , siginfo_t *info, void *context
 #endif
                                                );
     static PRCList          mPidLockList;
--- a/tools/trace-malloc/lib/nsTraceMalloc.c
+++ b/tools/trace-malloc/lib/nsTraceMalloc.c
@@ -1360,17 +1360,17 @@ NS_TraceMallocStartup(int logfd)
         /* Log everything in logfp (aka default_logfile)'s buffer to logfd. */
         logfp->fd = logfd;
         logfile_list = &default_logfile;
         logfp->prevp = &logfile_list;
         logfile_tail = &logfp->next;
         log_header(logfd);
     }
 
-    atexit(NS_TraceMallocShutdown);
+    RegisterTraceMallocShutdown();
 
     tmlock = PR_NewLock();
     (void) tm_get_thread(); /* ensure index initialization while it's easy */
 
     if (tracing_enabled)
         StartupHooker();
 }
 
--- a/tools/trace-malloc/lib/nsTypeInfo.cpp
+++ b/tools/trace-malloc/lib/nsTypeInfo.cpp
@@ -49,16 +49,32 @@
   by Patrick C. Beard.
  */
 
 #include <typeinfo>
 #include <ctype.h>
 
 extern "C" const char* nsGetTypeName(void* ptr);
 
+extern "C" void NS_TraceMallocShutdown();
+
+struct TraceMallocShutdown {
+    TraceMallocShutdown() {}
+    ~TraceMallocShutdown() {
+        NS_TraceMallocShutdown();
+    }
+};
+
+extern "C" void RegisterTraceMallocShutdown() {
+    // This instanciates the dummy class above, and will trigger the class
+    // destructor when libxul is unloaded. This is equivalent to atexit(),
+    // but gracefully handles dlclose().
+    static TraceMallocShutdown t;
+}
+
 class IUnknown {
 public:
     virtual long QueryInterface() = 0;
     virtual long AddRef() = 0;
     virtual long Release() = 0;
 };
 
 #if defined(MACOS)