Bug 804828 - Talagent trips ValidWriteAssert (when Firefox tries to restart in safe mode due to previous crashes). r=ted.
authorRafael Ávila de Espíndola <respindola@mozilla.com>
Wed, 31 Oct 2012 14:18:03 -0400
changeset 111941 d4fe281305ce2a77cac61f8576f13c69e957b194
parent 111940 ef5d003dbeacbcbce9775d6c3f8fdc06b6f0c503
child 111942 5f405fc4e3239b3719c95525b5c642dcfbc80e65
push id17344
push userrespindola@mozilla.com
push dateWed, 31 Oct 2012 20:55:40 +0000
treeherdermozilla-inbound@d4fe281305ce [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs804828
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 804828 - Talagent trips ValidWriteAssert (when Firefox tries to restart in safe mode due to previous crashes). r=ted.
toolkit/xre/nsAppRunner.cpp
xpcom/build/mozPoisonWrite.h
xpcom/build/mozPoisonWriteMac.cpp
xpcom/build/mozPoisonWriteStub.cpp
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -124,16 +124,17 @@ using mozilla::unused;
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsXULAppAPI.h"
 #include "nsXREDirProvider.h"
 #include "nsToolkitCompsCID.h"
 
 #include "nsINIParser.h"
 #include "mozilla/Omnijar.h"
 #include "mozilla/StartupTimeline.h"
+#include "mozilla/mozPoisonWrite.h"
 
 #include <stdlib.h>
 
 // for old system jemalloc version check
 #if !defined(MOZ_MEMORY) && defined(__NetBSD__)
 #include <sys/param.h>
 #endif
 
@@ -3869,16 +3870,20 @@ XREMain::XRE_main(int argc, char* argv[]
 #ifdef MOZ_INSTRUMENT_EVENT_LOOP
   mozilla::ShutdownEventTracing();
 #endif
 
   // Check for an application initiated restart.  This is one that
   // corresponds to nsIAppStartup.quit(eRestart)
   if (rv == NS_SUCCESS_RESTART_APP) {
     appInitiatedRestart = true;
+  } else {
+    // We will have a real shutdown, let ShutdownXPCOM poison writes to
+    // find any late ones.
+    mozilla::EnableWritePoisoning();
   }
 
   if (!mShuttingDown) {
 #ifdef MOZ_ENABLE_XREMOTE
     // shut down the x remote proxy window
     if (mRemoteService) {
       mRemoteService->Shutdown();
     }
--- a/xpcom/build/mozPoisonWrite.h
+++ b/xpcom/build/mozPoisonWrite.h
@@ -12,10 +12,11 @@ MOZ_BEGIN_EXTERN_C
   void MozillaUnRegisterDebugFD(int fd);
   void MozillaUnRegisterDebugFILE(FILE *f);
 MOZ_END_EXTERN_C
 
 #ifdef __cplusplus
 namespace mozilla {
 void PoisonWrite();
 void DisableWritePoisoning();
+void EnableWritePoisoning();
 }
 #endif
--- a/xpcom/build/mozPoisonWriteMac.cpp
+++ b/xpcom/build/mozPoisonWriteMac.cpp
@@ -271,17 +271,24 @@ public:
         return Lock;
     }
 
     MyAutoLock() : Scoped<AutoLockTraits>(getDebugFDsLock()) {
         PR_Lock(get());
     }
 };
 
-bool PoisoningDisabled = false;
+// This variable being true has two consequences
+// * It prevents PoisonWrite from patching the write functions.
+// * If the patching has already been done, it prevents AbortOnBadWrite from
+//   asserting. Note that not all writes use AbortOnBadWrite at this point
+//   (aio_write for example), so disabling writes after patching doesn't
+//   completely undo it.
+bool PoisoningDisabled = true;
+
 void AbortOnBadWrite(int fd, const void *wbuf, size_t count) {
     if (PoisoningDisabled)
         return;
 
     // Ignore writes of zero bytes, firefox does some during shutdown.
     if (count == 0)
         return;
 
@@ -370,17 +377,25 @@ extern "C" {
             return;
         fflush(f);
         MozillaUnRegisterDebugFD(fd);
     }
 }
 
 namespace mozilla {
 void PoisonWrite() {
-    PoisoningDisabled = false;
+    // Quick sanity check that we don't poison twice.
+    static bool WritesArePoisoned = false;
+    MOZ_ASSERT(!WritesArePoisoned);
+    if (WritesArePoisoned)
+        return;
+    WritesArePoisoned = true;
+
+    if (PoisoningDisabled)
+        return;
 
     nsCOMPtr<nsIFile> mozFile;
     NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mozFile));
     if (mozFile) {
         nsAutoCString nativePath;
         nsresult rv = mozFile->GetNativePath(nativePath);
         if (NS_SUCCEEDED(rv)) {
             sProfileDirectory = PL_strdup(nativePath.get());
@@ -399,9 +414,12 @@ void PoisonWrite() {
         mach_error_t t = mach_override_ptr(d->Function, d->Wrapper,
                                            &d->Buffer);
         MOZ_ASSERT(t == err_none);
     }
 }
 void DisableWritePoisoning() {
     PoisoningDisabled = true;
 }
+void EnableWritePoisoning() {
+    PoisoningDisabled = false;
 }
+}
--- a/xpcom/build/mozPoisonWriteStub.cpp
+++ b/xpcom/build/mozPoisonWriteStub.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include <stdio.h>
 namespace mozilla {
 void PoisonWrite() {
 }
 void DisableWritePoisoning() {
 }
+void EnableWritePoisoning() {
+}
 }
 extern "C" {
     void MozillaRegisterDebugFD(int fd) {
     }
     void MozillaUnRegisterDebugFD(int fd) {
     }
     void MozillaUnRegisterDebugFILE(FILE *f) {
     }