CrashReporterHelper.h (3633B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef mozilla_ipc_CrashReporterHelper_h 6 #define mozilla_ipc_CrashReporterHelper_h 7 8 #include "CrashReporterHost.h" 9 #include "mozilla/UniquePtr.h" 10 #include "nsIAppStartup.h" 11 #include "nsExceptionHandler.h" 12 #include "nsICrashService.h" 13 #include "nsPrintfCString.h" 14 #include "nsServiceManagerUtils.h" 15 16 namespace mozilla::ipc { 17 18 /** 19 * This class encapsulates the common elements of crash report handling for 20 * toplevel protocols representing processes. To use this class, you should: 21 * 22 * 1. Declare a method to initialize the crash reporter in your IPDL: 23 * `async InitCrashReporter(NativeThreadId threadId)` 24 * 25 * 2. Inherit from this class with the name of your derived class as the 26 * type parameter. Ex: `class MyClass : public CrashReporterHelper<MyClass>` 27 * 28 * 3. Provide a public `PROCESS_TYPE` constant for your class. Ex: 29 * 30 * ``` 31 * public: 32 * static constexpr GeckoProcessType PROCESS_TYPE = 33 * GeckoProcessType_GMPlugin; 34 * ``` 35 * 36 * 4. When your protocol actor is destroyed with a reason of `AbnormalShutdown`, 37 * you should call `GenerateCrashReport()`. If you need the crash 38 * report ID it will be copied in the second optional parameter upon 39 * successful crash report generation. 40 */ 41 template <class Derived> 42 class CrashReporterHelper { 43 public: 44 CrashReporterHelper() : mCrashReporter(nullptr) {} 45 IPCResult RecvInitCrashReporter( 46 const CrashReporter::CrashReporterInitArgs& aInitArgs) { 47 base::ProcessId pid = static_cast<Derived*>(this)->OtherPid(); 48 mCrashReporter = MakeUnique<ipc::CrashReporterHost>(Derived::PROCESS_TYPE, 49 pid, aInitArgs); 50 return IPC_OK(); 51 } 52 53 protected: 54 void GenerateCrashReport(nsString* aMinidumpId = nullptr) { 55 nsAutoString minidumpId; 56 if (!mCrashReporter) { 57 HandleOrphanedMinidump(minidumpId); 58 } else if (mCrashReporter->GenerateCrashReport()) { 59 minidumpId = mCrashReporter->MinidumpID(); 60 } 61 62 if (aMinidumpId) { 63 *aMinidumpId = minidumpId; 64 } 65 66 mCrashReporter = nullptr; 67 } 68 69 void MaybeTerminateProcess() { 70 if (PR_GetEnv("MOZ_CRASHREPORTER_SHUTDOWN")) { 71 NS_WARNING(nsPrintfCString("Shutting down due to %s process crash.", 72 XRE_GetProcessTypeString()) 73 .get()); 74 nsCOMPtr<nsIAppStartup> appService = 75 do_GetService("@mozilla.org/toolkit/app-startup;1"); 76 if (appService) { 77 bool userAllowedQuit = true; 78 appService->Quit(nsIAppStartup::eForceQuit, 1, &userAllowedQuit); 79 } 80 } 81 } 82 83 private: 84 void HandleOrphanedMinidump(nsString& aMinidumpId) { 85 base::ProcessId pid = static_cast<Derived*>(this)->OtherPid(); 86 if (CrashReporter::FinalizeOrphanedMinidump(pid, Derived::PROCESS_TYPE, 87 &aMinidumpId)) { 88 CrashReporterHost::RecordCrash(Derived::PROCESS_TYPE, 89 nsICrashService::CRASH_TYPE_CRASH, 90 aMinidumpId); 91 } else { 92 NS_WARNING(nsPrintfCString("child process pid = %" PRIPID 93 " crashed without leaving a minidump behind", 94 pid) 95 .get()); 96 } 97 } 98 99 protected: 100 UniquePtr<ipc::CrashReporterHost> mCrashReporter; 101 }; 102 103 } // namespace mozilla::ipc 104 105 #endif // mozilla_ipc_CrashReporterHelper_h