Report cycle collector faults to the error console and the observer service. Bug 410295, r+sr=peterv, a=schrep
authorbzbarsky@mit.edu
Sun, 06 Jan 2008 14:05:10 -0800
changeset 9932 ed8a27781493a3a00eab6acab643fd681f793afc
parent 9931 f396bd3d1a5495264071f5efc657bf98beba93d9
child 9933 34d67d9baa4c34891a1b74de6f7d30a25b0a3a5b
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersschrep
bugs410295
milestone1.9b3pre
Report cycle collector faults to the error console and the observer service. Bug 410295, r+sr=peterv, a=schrep
xpcom/base/nsCycleCollector.cpp
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -134,17 +134,19 @@
 #include "nsThreadUtils.h"
 #include "prenv.h"
 #include "prprf.h"
 #include "plstr.h"
 #include "prtime.h"
 #include "nsPrintfCString.h"
 #include "nsTArray.h"
 #include "nsIObserverService.h"
+#include "nsIConsoleService.h"
 #include "nsServiceManagerUtils.h"
+#include "nsThreadUtils.h"
 
 #include <stdio.h>
 #ifdef WIN32
 #include <io.h>
 #include <process.h>
 #endif
 
 #define DEFAULT_SHUTDOWN_COLLECTIONS 5
@@ -913,16 +915,43 @@ public:
 
 static nsCycleCollector *sCollector = nsnull;
 
 
 ////////////////////////////////////////////////////////////////////////
 // Utility functions
 ////////////////////////////////////////////////////////////////////////
 
+class CCRunnableFaultReport : public nsRunnable {
+public:
+    CCRunnableFaultReport(const nsCString& report)
+    {
+        CopyUTF8toUTF16(report, mReport);
+    }
+    
+    NS_IMETHOD Run() {
+        nsCOMPtr<nsIObserverService> obs =
+            do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
+        if (obs) {
+            obs->NotifyObservers(nsnull, "cycle-collector-fault",
+                                 mReport.get());
+        }
+
+        nsCOMPtr<nsIConsoleService> cons =
+            do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+        if (cons) {
+            cons->LogStringMessage(mReport.get());
+        }
+        return NS_OK;
+    }
+
+private:
+    nsString mReport;
+};
+
 static void
 Fault(const char *msg, const void *ptr=nsnull)
 {
 #ifdef DEBUG_CC
     // This should be nearly impossible, but just in case.
     if (!sCollector)
         return;
 
@@ -946,28 +975,33 @@ Fault(const char *msg, const void *ptr=n
             WriteGraph(stream, *sCurrGraph, ptr);
             fclose(stream);
         } 
 
         exit(1);
     }
 #endif
 
-    NS_NOTREACHED(nsPrintfCString(256,
-                  "Fault in cycle collector: %s (ptr: %p)\n",
-                  msg, ptr).get());
+    nsPrintfCString str(256, "Fault in cycle collector: %s (ptr: %p)\n",
+                        msg, ptr);
+    NS_NOTREACHED(str.get());
 
     // When faults are not fatal, we assume we're running in a
     // production environment and we therefore want to disable the
     // collector on a fault. This will unfortunately cause the browser
     // to leak pretty fast wherever creates cyclical garbage, but it's
     // probably a better user experience than crashing. Besides, we
     // *should* never hit a fault.
 
     sCollector->mParams.mDoNothing = PR_TRUE;
+
+    // Report to observers off an event so we don't run JS under GC
+    // (which is where we might be right now).
+    nsCOMPtr<nsIRunnable> ev = new CCRunnableFaultReport(str);
+    NS_DispatchToCurrentThread(ev);
 }
 
 #ifdef DEBUG_CC
 static void
 Fault(const char *msg, PtrInfo *pi)
 {
     printf("Fault in cycle collector: %s\n"
            "  while operating on pointer %p %s\n",