Bug 788512 - Actually generate Flash process dumps instead of just collecting them if present. r=bsmedberg,ted
authorGeorg Fritzsche <georg.fritzsche@googlemail.com>
Wed, 26 Sep 2012 22:49:20 +0200
changeset 110626 c8926a55f66113a960b3cbc8b51d376dce948c70
parent 110625 2b96e74420878cd94b9afd8fe4095196af24e46f
child 110627 1a7ebe9779c5795dc2d7409df0630debcba076ce
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersbsmedberg, ted
bugs788512
milestone19.0a1
Bug 788512 - Actually generate Flash process dumps instead of just collecting them if present. r=bsmedberg,ted
dom/plugins/ipc/PluginModuleParent.cpp
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/crashreporter/nsExceptionHandler.h
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -295,16 +295,37 @@ GetProcessCpuUsage(const InfallibleTArra
   }
 
   return true;
 }
 
 } // anonymous namespace
 #endif // #ifdef XP_WIN
 
+#ifdef MOZ_CRASHREPORTER_INJECTOR
+static bool
+CreateFlashMinidump(DWORD processId, ThreadId childThread,
+                    nsIFile* parentMinidump, const nsACString& name)
+{
+  if (processId == 0) {
+    return false;
+  }
+
+  base::ProcessHandle handle;
+  if (!base::OpenPrivilegedProcessHandle(processId, &handle)) {
+    return false;
+  }
+
+  bool res = CreateAdditionalChildMinidump(handle, 0, parentMinidump, name);
+  base::CloseProcessHandle(handle);
+
+  return res;
+}
+#endif
+
 bool
 PluginModuleParent::ShouldContinueFromReplyTimeout()
 {
 #ifdef MOZ_CRASHREPORTER
     CrashReporterParent* crashReporter = CrashReporter();
     crashReporter->AnnotateCrashReport(NS_LITERAL_CSTRING("PluginHang"),
                                        NS_LITERAL_CSTRING("1"));
     if (crashReporter->GeneratePairedMinidump(this)) {
@@ -317,29 +338,23 @@ PluginModuleParent::ShouldContinueFromRe
 
 #ifdef MOZ_CRASHREPORTER_INJECTOR
         nsCOMPtr<nsIFile> pluginDumpFile;
 
         if (GetMinidumpForID(mPluginDumpID, getter_AddRefs(pluginDumpFile)) &&
             pluginDumpFile) {
           nsCOMPtr<nsIFile> childDumpFile;
 
-          if (mFlashProcess1 &&
-              TakeMinidumpForChild(mFlashProcess1,
-                                   getter_AddRefs(childDumpFile))) {
+          if (CreateFlashMinidump(mFlashProcess1, 0, pluginDumpFile,
+                                  NS_LITERAL_CSTRING("flash1"))) {
             additionalDumps.Append(",flash1");
-            RenameAdditionalHangMinidump(pluginDumpFile, childDumpFile,
-                                         NS_LITERAL_CSTRING("flash1"));
           }
-          if (mFlashProcess2 &&
-              TakeMinidumpForChild(mFlashProcess2,
-                                   getter_AddRefs(childDumpFile))) {
+          if (CreateFlashMinidump(mFlashProcess2, 0, pluginDumpFile,
+                                  NS_LITERAL_CSTRING("flash2"))) {
             additionalDumps.Append(",flash2");
-            RenameAdditionalHangMinidump(pluginDumpFile, childDumpFile,
-                                         NS_LITERAL_CSTRING("flash2"));
           }
         }
 #endif
 
         crashReporter->AnnotateCrashReport(
             NS_LITERAL_CSTRING("additional_minidumps"),
             additionalDumps);
     } else {
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -2655,33 +2655,43 @@ CurrentThreadId()
       return i;
   }
   abort();
 #else
 #  error "Unsupported platform"
 #endif
 }
 
+#ifdef XP_MACOSX
+static mach_port_t
+GetChildThread(ProcessHandle childPid, ThreadId childBlamedThread)
+{
+  mach_port_t childThread = MACH_PORT_NULL;
+  thread_act_port_array_t   threads_for_task;
+  mach_msg_type_number_t    thread_count;
+
+  if (task_threads(childPid, &threads_for_task, &thread_count)
+      == KERN_SUCCESS && childBlamedThread < thread_count) {
+    childThread = threads_for_task[childBlamedThread];
+  }
+
+  return childThread;
+}
+#endif
+
 bool
 CreatePairedMinidumps(ProcessHandle childPid,
                       ThreadId childBlamedThread,
                       nsIFile** childDump)
 {
   if (!GetEnabled())
     return false;
 
 #ifdef XP_MACOSX
-  mach_port_t childThread = MACH_PORT_NULL;
-  thread_act_port_array_t   threads_for_task;
-  mach_msg_type_number_t    thread_count;
-
-  if (task_threads(childPid, &threads_for_task, &thread_count)
-      == KERN_SUCCESS && childBlamedThread < thread_count) {
-    childThread = threads_for_task[childBlamedThread];
-  }
+  mach_port_t childThread = GetChildThread(childPid, childBlamedThread);
 #else
   ThreadId childThread = childBlamedThread;
 #endif
 
   xpstring dump_path;
 #ifndef XP_LINUX
   dump_path = gExceptionHandler->dump_path();
 #else
@@ -2727,16 +2737,54 @@ CreatePairedMinidumps(ProcessHandle chil
   }
 
   childMinidump.forget(childDump);
 
   return true;
 }
 
 bool
+CreateAdditionalChildMinidump(ProcessHandle childPid,
+                              ThreadId childBlamedThread,
+                              nsIFile* parentMinidump,
+                              const nsACString& name)
+{
+  if (!GetEnabled())
+    return false;
+
+#ifdef XP_MACOSX
+  mach_port_t childThread = GetChildThread(childPid, childBlamedThread);
+#else
+  ThreadId childThread = childBlamedThread;
+#endif
+
+  xpstring dump_path;
+#ifndef XP_LINUX
+  dump_path = gExceptionHandler->dump_path();
+#else
+  dump_path = gExceptionHandler->minidump_descriptor().directory();
+#endif
+
+  // dump the child
+  nsCOMPtr<nsIFile> childMinidump;
+  if (!google_breakpad::ExceptionHandler::WriteMinidumpForChild(
+         childPid,
+         childThread,
+         dump_path,
+         PairedDumpCallback,
+         static_cast<void*>(&childMinidump))) {
+    return false;
+  }
+
+  RenameAdditionalHangMinidump(childMinidump, parentMinidump, name);
+
+  return true;
+}
+
+bool
 UnsetRemoteExceptionHandler()
 {
   delete gExceptionHandler;
   gExceptionHandler = NULL;
   return true;
 }
 
 #if defined(MOZ_WIDGET_ANDROID)
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -102,28 +102,37 @@ typedef int ThreadId;
 // XXX: this is a somewhat out-of-place interface to expose through
 // crashreporter, but it takes significant work to call sys_gettid()
 // correctly on Linux and breakpad has already jumped through those
 // hoops for us.
 ThreadId CurrentThreadId();
 
 // Create a hang report with two minidumps that are snapshots of the state
 // of this parent process and |childPid|. The "main" minidump will be the
-// child process, and this parent process will have the _browser extension.
+// child process, and this parent process will have the -browser extension.
 //
 // Returns true on success. If this function fails, it will attempt to delete
 // any files that were created.
 //
 // The .extra information created will not include an additional_minidumps
 // annotation: the caller should annotate additional_minidumps with
 // at least "browser" and perhaps other minidumps attached to this report.
 bool CreatePairedMinidumps(ProcessHandle childPid,
                            ThreadId childBlamedThread,
                            nsIFile** childDump);
 
+// Create an additional minidump for a child of a process which already has
+// a minidump (|parentMinidump|).
+// The resulting dump will get the id of the parent and use the |name| as
+// an extension.
+bool CreateAdditionalChildMinidump(ProcessHandle childPid,
+                                   ThreadId childBlamedThread,
+                                   nsIFile* parentMinidump,
+                                   const nsACString& name);
+
 #  if defined(XP_WIN32) || defined(XP_MACOSX)
 // Parent-side API for children
 const char* GetChildNotificationPipe();
 
 #ifdef MOZ_CRASHREPORTER_INJECTOR
 // Inject a crash report client into an arbitrary process, and inform the
 // callback object when it crashes. Parent process only.