Bug 1481009 Part 3 - Report recording/replaying processes crashes as if they happened in the middleman, r=gsvelto.
authorBrian Hackett <bhackett1024@gmail.com>
Mon, 13 Aug 2018 20:46:42 +0000
changeset 431341 7927150efaa6b6ea07e56d2b1e144171e2150046
parent 431340 5b2072d947e67e065e1186cc599680be3b2ae691
child 431342 d605332894bff2a8eee8667463e35b76e0f2f791
push id34437
push userebalazs@mozilla.com
push dateTue, 14 Aug 2018 09:31:09 +0000
treeherdermozilla-central@914b3b370ad0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgsvelto
bugs1481009
milestone63.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 1481009 Part 3 - Report recording/replaying processes crashes as if they happened in the middleman, r=gsvelto.
toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc
toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc
toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h
toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/recordreplay/ipc/DisabledIPC.cpp
toolkit/recordreplay/ipc/ParentIPC.cpp
toolkit/recordreplay/ipc/ParentIPC.h
--- a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_client.cc
@@ -27,16 +27,18 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "mac/crash_generation/crash_generation_client.h"
 
 #include "mac/crash_generation/crash_generation_server.h"
 #include "common/mac/MachIPC.h"
 
+#include "mozilla/recordreplay/ChildIPC.h"
+
 namespace google_breakpad {
 
 bool CrashGenerationClient::RequestDumpForException(
     int exception_type,
     int exception_code,
     int exception_subcode,
     mach_port_t crashing_thread) {
   // The server will send a message to this port indicating that it
@@ -48,16 +50,24 @@ bool CrashGenerationClient::RequestDumpF
   message.AddDescriptor(crashing_thread);             // crashing thread
   message.AddDescriptor(MACH_PORT_NULL);              // handler thread
   message.AddDescriptor(acknowledge_port.GetPort());  // message receive port
 
   ExceptionInfo info;
   info.exception_type = exception_type;
   info.exception_code = exception_code;
   info.exception_subcode = exception_subcode;
+  info.child_pid = getpid();
+
+  // When recording/replaying, associate minidumps with the middleman process
+  // so that the UI process can find them.
+  if (mozilla::recordreplay::IsRecordingOrReplaying()) {
+    info.child_pid = mozilla::recordreplay::child::MiddlemanProcessId();
+  }
+
   message.SetData(&info, sizeof(info));
 
   const mach_msg_timeout_t kSendTimeoutMs = 2 * 1000;
   kern_return_t result = sender_.SendMessage(message, kSendTimeoutMs);
   if (result != KERN_SUCCESS)
     return false;
 
   // Give the server slightly longer to reply since it has to
--- a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.cc
@@ -105,19 +105,17 @@ bool CrashGenerationServer::WaitForOneMe
     switch (message.GetMessageID()) {
       case kDumpRequestMessage: {
         ExceptionInfo &info = (ExceptionInfo &)*message.GetData();
       
         mach_port_t remote_task = message.GetTranslatedPort(0);
         mach_port_t crashing_thread = message.GetTranslatedPort(1);
         mach_port_t handler_thread = message.GetTranslatedPort(2);
         mach_port_t ack_port = message.GetTranslatedPort(3);
-        pid_t remote_pid = -1;
-        pid_for_task(remote_task, &remote_pid);
-        ClientInfo client(remote_pid);
+        ClientInfo client(info.child_pid);
 
         bool result;
         std::string dump_path;
         if (generate_dumps_ && (!filter_ || filter_(filter_context_))) {
           ScopedTaskSuspend suspend(remote_task);
 
           MinidumpGenerator generator(remote_task, handler_thread);
           dump_path = generator.UniqueNameInDirectory(dump_dir_, NULL);
--- a/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/crash_generation_server.h
@@ -47,16 +47,17 @@ enum {
   kQuitMessage            = 3
 };
 
 // Exception details sent by the client when requesting a dump.
 struct ExceptionInfo {
   int32_t exception_type;
   int32_t exception_code;
   int32_t exception_subcode;
+  int32_t child_pid;
 };
 
 class CrashGenerationServer {
  public:
   // WARNING: callbacks may be invoked on a different thread
   // than that which creates the CrashGenerationServer.  They must
   // be thread safe.
   typedef void (*OnClientDumpRequestCallback)(void *context,
--- a/toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build
+++ b/toolkit/crashreporter/breakpad-client/mac/crash_generation/moz.build
@@ -7,14 +7,15 @@
 UNIFIED_SOURCES += [
     'crash_generation_client.cc',
     'crash_generation_server.cc',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
+    '/ipc/chromium/src',
     '/toolkit/crashreporter/breakpad-client',
     '/toolkit/crashreporter/google-breakpad/src',
 ]
 
 if CONFIG['CC_TYPE'] == 'clang':
     CXXFLAGS += ['-Wno-shadow']
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -89,16 +89,17 @@ using mozilla::InjectCrashRunnable;
 #include "nsCRT.h"
 #include "nsIFile.h"
 #include <map>
 #include <vector>
 
 #include "mozilla/IOInterposer.h"
 #include "mozilla/mozalloc_oom.h"
 #include "mozilla/WindowsDllBlocklist.h"
+#include "mozilla/recordreplay/ParentIPC.h"
 
 #if defined(XP_MACOSX)
 CFStringRef reporterClientAppID = CFSTR("org.mozilla.crashreporter");
 #endif
 #if defined(MOZ_WIDGET_ANDROID)
 #include "common/linux/file_id.h"
 #endif
 
@@ -3247,16 +3248,34 @@ OnChildProcessDumpRequested(void* aConte
     }
 #ifdef MOZ_CRASHREPORTER_INJECTOR
     if (runCallback)
       NS_DispatchToMainThread(new ReportInjectedCrash(pid));
 #endif
   }
 }
 
+#ifdef XP_MACOSX
+
+// Middleman processes do not have their own crash generation server.
+// Any crashes in the middleman's children are forwarded to the UI process.
+static bool
+MaybeForwardCrashesIfMiddleman()
+{
+  if (recordreplay::IsMiddleman()) {
+    childCrashNotifyPipe =
+      mozilla::Smprintf("gecko-crash-server-pipe.%i",
+                        static_cast<int>(recordreplay::parent::ParentProcessId())).release();
+    return true;
+  }
+  return false;
+}
+
+#endif // XP_MACOSX
+
 static bool
 OOPInitialized()
 {
   return pidToMinidump != nullptr;
 }
 
 void
 OOPInit()
@@ -3335,16 +3354,20 @@ OOPInit()
   crashServer = new CrashGenerationServer(
     serverSocketFd,
     OnChildProcessDumpRequested, nullptr,
     nullptr, nullptr,           // we don't care about process exit here
     true,
     &dumpPath);
 
 #elif defined(XP_MACOSX)
+  if (MaybeForwardCrashesIfMiddleman()) {
+    return;
+  }
+
   childCrashNotifyPipe =
     mozilla::Smprintf("gecko-crash-server-pipe.%i",
                static_cast<int>(getpid())).release();
   const std::string dumpPath = gExceptionHandler->dump_path();
 
   crashServer = new CrashGenerationServer(
     childCrashNotifyPipe,
     nullptr,
--- a/toolkit/recordreplay/ipc/DisabledIPC.cpp
+++ b/toolkit/recordreplay/ipc/DisabledIPC.cpp
@@ -160,12 +160,18 @@ OpenChannel(base::ProcessId aMiddlemanPi
 void
 GetArgumentsForChildProcess(base::ProcessId aMiddlemanPid, uint32_t aChannelId,
                             const char* aRecordingFile, bool aRecording,
                             std::vector<std::string>& aExtraArgs)
 {
   MOZ_CRASH();
 }
 
+base::ProcessId
+ParentProcessId()
+{
+  MOZ_CRASH();
+}
+
 } // namespace parent
 
 } // namespace recordreplay
 } // namespace mozilla
--- a/toolkit/recordreplay/ipc/ParentIPC.cpp
+++ b/toolkit/recordreplay/ipc/ParentIPC.cpp
@@ -844,23 +844,33 @@ ActiveChildTargetCheckpoint()
 static MessageLoop* gMainThreadMessageLoop;
 
 MessageLoop*
 MainThreadMessageLoop()
 {
   return gMainThreadMessageLoop;
 }
 
+static base::ProcessId gParentPid;
+
+base::ProcessId
+ParentProcessId()
+{
+  return gParentPid;
+}
+
 void
 InitializeMiddleman(int aArgc, char* aArgv[], base::ProcessId aParentPid,
                     const base::SharedMemoryHandle& aPrefsHandle,
                     const ipc::FileDescriptor& aPrefMapHandle)
 {
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
 
+  gParentPid = aParentPid;
+
   // Construct the message that will be sent to each child when starting up.
   IntroductionMessage* msg =
     IntroductionMessage::New(aParentPid, aArgc, aArgv);
   ChildProcessInfo::SetIntroductionMessage(msg);
 
   MOZ_RELEASE_ASSERT(gProcessKind == ProcessKind::MiddlemanRecording ||
                      gProcessKind == ProcessKind::MiddlemanReplaying);
 
--- a/toolkit/recordreplay/ipc/ParentIPC.h
+++ b/toolkit/recordreplay/ipc/ParentIPC.h
@@ -32,16 +32,19 @@ namespace parent {
 // Initialize state in a UI process.
 void InitializeUIProcess(int aArgc, char** aArgv);
 
 // Get any directory where content process recordings should be saved.
 const char* SaveAllRecordingsDirectory();
 
 // Middleman process API
 
+// Get the pid of the UI process.
+base::ProcessId ParentProcessId();
+
 // Save the recording up to the current point in execution.
 void SaveRecording(const ipc::FileDescriptor& aFile);
 
 // Get the message channel used to communicate with the UI process.
 ipc::MessageChannel* ChannelToUIProcess();
 
 // Initialize state in a middleman process.
 void InitializeMiddleman(int aArgc, char* aArgv[], base::ProcessId aParentPid,