Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef mozilla_ipc_CrashReporterHost_h
8 : #define mozilla_ipc_CrashReporterHost_h
9 :
10 : #include <functional>
11 :
12 : #include "mozilla/UniquePtr.h"
13 : #include "mozilla/ipc/Shmem.h"
14 : #include "base/process.h"
15 : #ifdef MOZ_CRASHREPORTER
16 : #include "nsExceptionHandler.h"
17 : #endif
18 : #include "nsIThread.h"
19 :
20 : namespace mozilla {
21 : namespace ipc {
22 :
23 : class GeckoChildProcessHost;
24 :
25 : // This is the newer replacement for CrashReporterParent. It is created in
26 : // response to a InitCrashReporter message on a top-level actor, and simply
27 : // holds the metadata shmem alive until the process ends. When the process
28 : // terminates abnormally, the top-level should call GenerateCrashReport to
29 : // automatically integrate metadata.
30 0 : class CrashReporterHost
31 : {
32 : typedef mozilla::ipc::Shmem Shmem;
33 : #ifdef MOZ_CRASHREPORTER
34 : typedef CrashReporter::AnnotationTable AnnotationTable;
35 : typedef CrashReporter::ThreadId ThreadId;
36 : #else
37 : // unused in this case
38 : typedef int32_t ThreadId;
39 : #endif
40 :
41 : public:
42 :
43 : template <typename T>
44 1 : class CallbackWrapper {
45 : public:
46 0 : void Init(std::function<void(T)>&& aCallback, bool aAsync)
47 : {
48 0 : mCallback = Move(aCallback);
49 0 : mAsync = aAsync;
50 0 : if (IsAsync()) {
51 : // Don't call do_GetCurrentThread() is this is called synchronously
52 : // because 1. it's unnecessary, and 2. more importantly, it might create
53 : // one if called from a native thread, and the thread will be leaked.
54 0 : mTargetThread = do_GetCurrentThread();
55 : }
56 0 : }
57 :
58 0 : bool IsEmpty()
59 : {
60 0 : return !mCallback;
61 : }
62 :
63 0 : bool IsAsync()
64 : {
65 0 : return mAsync;
66 : }
67 :
68 0 : void Invoke(T aResult)
69 : {
70 0 : if (IsAsync()) {
71 0 : decltype(mCallback) callback = Move(mCallback);
72 0 : mTargetThread->
73 0 : Dispatch(NS_NewRunnableFunction("ipc::CrashReporterHost::CallbackWrapper::Invoke",
74 0 : [callback, aResult](){
75 0 : callback(aResult);
76 0 : }), NS_DISPATCH_NORMAL);
77 : } else {
78 0 : MOZ_ASSERT(!mTargetThread);
79 0 : mCallback(aResult);
80 : }
81 :
82 0 : Clear();
83 0 : }
84 :
85 : private:
86 0 : void Clear()
87 : {
88 0 : mCallback = nullptr;
89 0 : mTargetThread = nullptr;
90 0 : mAsync = false;
91 0 : }
92 :
93 : bool mAsync;
94 : std::function<void(T)> mCallback;
95 : nsCOMPtr<nsIThread> mTargetThread;
96 : };
97 :
98 : CrashReporterHost(GeckoProcessType aProcessType,
99 : const Shmem& aShmem,
100 : ThreadId aThreadId);
101 :
102 : #ifdef MOZ_CRASHREPORTER
103 : // Helper function for generating a crash report for a process that probably
104 : // crashed (i.e., had an AbnormalShutdown in ActorDestroy). Returns true if
105 : // the process has a minidump attached and we were able to generate a report.
106 : bool GenerateCrashReport(base::ProcessId aPid);
107 :
108 : // Given an existing minidump for a crashed child process, take ownership of
109 : // it from IPDL. After this, FinalizeCrashReport may be called.
110 : RefPtr<nsIFile> TakeCrashedChildMinidump(base::ProcessId aPid, uint32_t* aOutSequence);
111 :
112 : // Replace the stored minidump with a new one. After this,
113 : // FinalizeCrashReport may be called.
114 : bool AdoptMinidump(nsIFile* aFile);
115 :
116 : // If a minidump was already captured (e.g. via the hang reporter), this
117 : // finalizes the existing report by attaching metadata and notifying the
118 : // crash service.
119 : bool FinalizeCrashReport();
120 :
121 : // Generate a paired minidump. This does not take the crash report, as
122 : // GenerateCrashReport does. After this, FinalizeCrashReport may be called.
123 : // Minidump(s) can be generated synchronously or asynchronously, specified in
124 : // argument aAsync. When the operation completes, aCallback is invoked, where
125 : // the callback argument denotes whether the operation succeeded.
126 : void
127 : GenerateMinidumpAndPair(GeckoChildProcessHost* aChildProcess,
128 : nsIFile* aMinidumpToPair,
129 : const nsACString& aPairName,
130 : std::function<void(bool)>&& aCallback,
131 : bool aAsync);
132 :
133 : // This is a static helper function to notify the crash service that a
134 : // crash has occurred. When PCrashReporter is removed, we can make this
135 : // a member function. This can be called from any thread, and if not
136 : // called from the main thread, will post a synchronous message to the
137 : // main thread.
138 : static void NotifyCrashService(
139 : GeckoProcessType aProcessType,
140 : const nsString& aChildDumpID,
141 : const AnnotationTable* aNotes);
142 :
143 : void AddNote(const nsCString& aKey, const nsCString& aValue);
144 :
145 0 : bool HasMinidump() const {
146 0 : return !mDumpID.IsEmpty();
147 : }
148 0 : const nsString& MinidumpID() const {
149 0 : MOZ_ASSERT(HasMinidump());
150 0 : return mDumpID;
151 : }
152 : #endif
153 :
154 : private:
155 : static void AsyncAddCrash(int32_t aProcessType, int32_t aCrashType,
156 : const nsString& aChildDumpID);
157 :
158 : private:
159 : CallbackWrapper<bool> mCreateMinidumpCallback;
160 : GeckoProcessType mProcessType;
161 : Shmem mShmem;
162 : ThreadId mThreadId;
163 : time_t mStartTime;
164 : #ifdef MOZ_CRASHREPORTER
165 : AnnotationTable mExtraNotes;
166 : #endif
167 : nsString mDumpID;
168 : bool mFinalized;
169 : nsCOMPtr<nsIFile> mTargetDump;
170 : };
171 :
172 : } // namespace ipc
173 : } // namespace mozilla
174 :
175 : #endif // mozilla_ipc_CrashReporterHost_h
|