Bug 1039575 - Hook up crash reporting for GMP plugins to the point where we have a crash ID in GMPParent::ActorDestroy, r=ted
authorBenjamin Smedberg <benjamin@smedbergs.us>
Fri, 18 Jul 2014 13:35:44 -0400
changeset 215756 55762bee8f273e5b24caa8d69de97f353c8e0758
parent 215755 fcb0e9c6c148eeb22093bcb33b37fd4664567d57
child 215757 ad15134168117f116363e1174c0846465f2d9f15
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1039575
milestone33.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 1039575 - Hook up crash reporting for GMP plugins to the point where we have a crash ID in GMPParent::ActorDestroy, r=ted * * * Bug 1039575 followup - always return from GMPChild
content/media/gmp/GMPChild.cpp
content/media/gmp/GMPChild.h
content/media/gmp/GMPParent.cpp
content/media/gmp/GMPParent.h
content/media/gmp/PGMP.ipdl
dom/ipc/PCrashReporter.ipdl
--- a/content/media/gmp/GMPChild.cpp
+++ b/content/media/gmp/GMPChild.cpp
@@ -7,16 +7,19 @@
 #include "GMPVideoDecoderChild.h"
 #include "GMPVideoEncoderChild.h"
 #include "GMPVideoHost.h"
 #include "nsIFile.h"
 #include "nsXULAppAPI.h"
 #include "gmp-video-decode.h"
 #include "gmp-video-encode.h"
 #include "GMPPlatform.h"
+#include "mozilla/dom/CrashReporterChild.h"
+
+using mozilla::dom::CrashReporterChild;
 
 #ifdef XP_WIN
 #include <stdlib.h> // for _exit()
 #else
 #include <unistd.h> // for _exit()
 #endif
 
 #if defined(XP_WIN)
@@ -39,16 +42,19 @@ GMPChild::~GMPChild()
 }
 
 bool
 GMPChild::Init(const std::string& aPluginPath,
                base::ProcessHandle aParentProcessHandle,
                MessageLoop* aIOLoop,
                IPC::Channel* aChannel)
 {
+#ifdef MOZ_CRASHREPORTER
+  SendPCrashReporterConstructor(CrashReporter::CurrentThreadId());
+#endif
 #if defined(XP_WIN)
   mozilla::SandboxTarget::Instance()->StartSandbox();
 #endif
   return LoadPluginLibrary(aPluginPath) &&
          Open(aChannel, aParentProcessHandle, aIOLoop);
 }
 
 bool
@@ -148,16 +154,29 @@ GMPChild::ProcessingError(Result aWhat)
       MOZ_CRASH("aborting because of MsgRouteError");
     case MsgValueError:
       MOZ_CRASH("aborting because of MsgValueError");
     default:
       MOZ_CRASH("not reached");
   }
 }
 
+mozilla::dom::PCrashReporterChild*
+GMPChild::AllocPCrashReporterChild(const NativeThreadId& aThread)
+{
+  return new CrashReporterChild();
+}
+
+bool
+GMPChild::DeallocPCrashReporterChild(PCrashReporterChild* aCrashReporter)
+{
+  delete aCrashReporter;
+  return true;
+}
+
 PGMPVideoDecoderChild*
 GMPChild::AllocPGMPVideoDecoderChild()
 {
   return new GMPVideoDecoderChild(this);
 }
 
 bool
 GMPChild::DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor)
--- a/content/media/gmp/GMPChild.h
+++ b/content/media/gmp/GMPChild.h
@@ -22,16 +22,18 @@ public:
   bool Init(const std::string& aPluginPath,
             base::ProcessHandle aParentProcessHandle,
             MessageLoop* aIOLoop,
             IPC::Channel* aChannel);
   bool LoadPluginLibrary(const std::string& aPluginPath);
   MessageLoop* GMPMessageLoop();
 
 private:
+  virtual PCrashReporterChild* AllocPCrashReporterChild(const NativeThreadId& aThread) MOZ_OVERRIDE;
+  virtual bool DeallocPCrashReporterChild(PCrashReporterChild*) MOZ_OVERRIDE;
   virtual PGMPVideoDecoderChild* AllocPGMPVideoDecoderChild() MOZ_OVERRIDE;
   virtual bool DeallocPGMPVideoDecoderChild(PGMPVideoDecoderChild* aActor) MOZ_OVERRIDE;
   virtual PGMPVideoEncoderChild* AllocPGMPVideoEncoderChild() MOZ_OVERRIDE;
   virtual bool DeallocPGMPVideoEncoderChild(PGMPVideoEncoderChild* aActor) MOZ_OVERRIDE;
   virtual bool RecvPGMPVideoDecoderConstructor(PGMPVideoDecoderChild* aActor) MOZ_OVERRIDE;
   virtual bool RecvPGMPVideoEncoderConstructor(PGMPVideoEncoderChild* aActor) MOZ_OVERRIDE;
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
   virtual void ProcessingError(Result aWhat) MOZ_OVERRIDE;
--- a/content/media/gmp/GMPParent.cpp
+++ b/content/media/gmp/GMPParent.cpp
@@ -10,16 +10,24 @@
 #include "nsILineInputStream.h"
 #include "nsNetUtil.h"
 #include "nsCharSeparatedTokenizer.h"
 #include "nsThreadUtils.h"
 #include "nsIRunnable.h"
 #include "mozIGeckoMediaPluginService.h"
 #include "mozilla/unused.h"
 
+#ifdef MOZ_CRASHREPORTER
+#include "mozilla/dom/CrashReporterParent.h"
+
+using mozilla::dom::CrashReporterParent;
+using CrashReporter::AnnotationTable;
+using CrashReporter::GetIDFromMinidump;
+#endif
+
 namespace mozilla {
 namespace gmp {
 
 GMPParent::GMPParent()
   : mState(GMPStateNotLoaded)
   , mProcess(nullptr)
 {
 }
@@ -238,22 +246,82 @@ GMPParent::GetGMPVideoEncoder(GMPVideoEn
   }
   nsRefPtr<GMPVideoEncoderParent> vep = static_cast<GMPVideoEncoderParent*>(pvep);
   mVideoEncoders.AppendElement(vep);
   vep.forget(aGMPVE);
 
   return NS_OK;
 }
 
+#ifdef MOZ_CRASHREPORTER
+void
+GMPParent::WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes)
+{
+  notes.Put(NS_LITERAL_CSTRING("GMPPlugin"), NS_LITERAL_CSTRING("1"));
+  notes.Put(NS_LITERAL_CSTRING("PluginFilename"),
+                               NS_ConvertUTF16toUTF8(mName));
+  notes.Put(NS_LITERAL_CSTRING("PluginName"), mDisplayName);
+  notes.Put(NS_LITERAL_CSTRING("PluginVersion"), mVersion);
+}
+
+void
+GMPParent::GetCrashID(nsString& aResult)
+{
+  CrashReporterParent* cr = nullptr;
+  if (ManagedPCrashReporterParent().Length() > 0) {
+    cr = static_cast<CrashReporterParent*>(ManagedPCrashReporterParent()[0]);
+  }
+  if (NS_WARN_IF(!cr)) {
+    return;
+  }
+
+  AnnotationTable notes(4);
+  WriteExtraDataForMinidump(notes);
+  nsCOMPtr<nsIFile> dumpFile;
+  TakeMinidump(getter_AddRefs(dumpFile), nullptr);
+  if (!dumpFile) {
+    NS_WARNING("GMP crash without crash report");
+    return;
+  }
+  GetIDFromMinidump(dumpFile, aResult);
+  cr->GenerateCrashReportForMinidump(dumpFile, &notes);
+}
+#endif
+
 void
 GMPParent::ActorDestroy(ActorDestroyReason aWhy)
 {
+  if (AbnormalShutdown == aWhy) {
+    nsString dumpID;
+#ifdef MOZ_CRASHREPORTER
+    GetCrashID(dumpID);
+#endif
+    // now do something with the crash ID, bug 1038961
+  }
   UnloadProcess();
 }
 
+mozilla::dom::PCrashReporterParent*
+GMPParent::AllocPCrashReporterParent(const NativeThreadId& aThread)
+{
+#ifndef MOZ_CRASHREPORTER
+  MOZ_ASSERT(false, "Should only be sent if crash reporting is enabled.");
+#endif
+  CrashReporterParent* cr = new CrashReporterParent();
+  cr->SetChildData(aThread, GeckoProcessType_GMPlugin);
+  return cr;
+}
+
+bool
+GMPParent::DeallocPCrashReporterParent(PCrashReporterParent* aCrashReporter)
+{
+  delete aCrashReporter;
+  return true;
+}
+
 PGMPVideoDecoderParent*
 GMPParent::AllocPGMPVideoDecoderParent()
 {
   GMPVideoDecoderParent* vdp = new GMPVideoDecoderParent(this);
   NS_ADDREF(vdp);
   return vdp;
 }
 
--- a/content/media/gmp/GMPParent.h
+++ b/content/media/gmp/GMPParent.h
@@ -16,16 +16,27 @@
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsIFile.h"
 #include "ThreadSafeRefcountingWithMainThreadDestruction.h"
 
 class nsILineInputStream;
 class nsIThread;
 
+#ifdef MOZ_CRASHREPORTER
+#include "nsExceptionHandler.h"
+
+namespace mozilla {
+namespace dom {
+class PCrashReporterParent;
+class CrashReporterParent;
+}
+}
+#endif
+
 namespace mozilla {
 namespace gmp {
 
 class GMPCapability
 {
 public:
   nsCString mAPIName;
   nsTArray<nsCString> mAPITags;
@@ -81,17 +92,24 @@ public:
   already_AddRefed<nsIFile> GetDirectory() {
     return nsCOMPtr<nsIFile>(mDirectory).forget();
   }
 
 private:
   ~GMPParent();
   bool EnsureProcessLoaded();
   nsresult ReadGMPMetaData();
+#ifdef MOZ_CRASHREPORTER
+  void WriteExtraDataForMinidump(CrashReporter::AnnotationTable& notes);
+  void GetCrashID(nsString& aResult);
+#endif
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
+
+  virtual PCrashReporterParent* AllocPCrashReporterParent(const NativeThreadId& aThread) MOZ_OVERRIDE;
+  virtual bool DeallocPCrashReporterParent(PCrashReporterParent* aCrashReporter) MOZ_OVERRIDE;
   virtual PGMPVideoDecoderParent* AllocPGMPVideoDecoderParent() MOZ_OVERRIDE;
   virtual bool DeallocPGMPVideoDecoderParent(PGMPVideoDecoderParent* aActor) MOZ_OVERRIDE;
   virtual PGMPVideoEncoderParent* AllocPGMPVideoEncoderParent() MOZ_OVERRIDE;
   virtual bool DeallocPGMPVideoEncoderParent(PGMPVideoEncoderParent* aActor) MOZ_OVERRIDE;
 
   GMPState mState;
   nsCOMPtr<nsIFile> mDirectory; // plugin directory on disk
   nsString mName; // base name of plugin on disk, UTF-16 because used for paths
--- a/content/media/gmp/PGMP.ipdl
+++ b/content/media/gmp/PGMP.ipdl
@@ -1,22 +1,30 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PGMPVideoDecoder;
 include protocol PGMPVideoEncoder;
+include protocol PCrashReporter;
+
+using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h";
 
 namespace mozilla {
 namespace gmp {
 
 intr protocol PGMP
 {
   manages PGMPVideoDecoder;
   manages PGMPVideoEncoder;
+  manages PCrashReporter;
+
+parent:
+  async PCrashReporter(NativeThreadId tid);
+
 child:
   async PGMPVideoDecoder();
   async PGMPVideoEncoder();
 };
 
 } // namespace gmp
 } // namespace mozilla
--- a/dom/ipc/PCrashReporter.ipdl
+++ b/dom/ipc/PCrashReporter.ipdl
@@ -1,30 +1,31 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set sw=4 ts=8 et tw=80 : 
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PContent;
 include protocol PPluginModule;
+include protocol PGMP;
 
 namespace mozilla {
 namespace dom {
 
 struct Mapping {
   nsCString library_name;
   nsCString file_id;
   uintptr_t start_address;
   size_t mapping_length;
   size_t file_offset;
 };
 
 intr protocol PCrashReporter {
-  manager PContent or PPluginModule;
+  manager PContent or PPluginModule or PGMP;
 parent:
   AnnotateCrashReport(nsCString key, nsCString data);
   AppendAppNotes(nsCString data);
   __delete__();
 };
 
 }
 }