1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 // This header has two implementations, the real one in nsExceptionHandler.cpp
7 // and a dummy in nsDummyExceptionHandler.cpp. The latter is used in builds
8 // configured with --disable-crashreporter. If you add or remove a function
9 // from this header you must update both implementations otherwise you'll break
10 // builds that disable the crash reporter.
12 #ifndef nsExceptionHandler_h__
13 #define nsExceptionHandler_h__
15 #include "mozilla/Assertions.h"
16 #include "mozilla/EnumeratedArray.h"
17 #include "mozilla/Maybe.h"
19 #include "CrashAnnotations.h"
23 #include "nsXULAppAPI.h"
29 # ifdef WIN32_LEAN_AND_MEAN
30 # undef WIN32_LEAN_AND_MEAN
35 #if defined(XP_MACOSX)
36 # include <mach/mach.h>
45 namespace CrashReporter
{
48 using mozilla::Nothing
;
51 * Returns true if the crash reporter is using the dummy implementation.
53 static inline bool IsDummy() {
54 #ifdef MOZ_CRASHREPORTER
61 nsresult
SetExceptionHandler(nsIFile
* aXREDirectory
, bool force
= false);
62 nsresult
UnsetExceptionHandler();
65 * Tell the crash reporter to recalculate where crash events files should go.
66 * SetCrashEventsDir is used before XPCOM is initialized from the startup
69 * UpdateCrashEventsDir uses the directory service to re-set the
70 * crash event directory based on the current profile.
72 * 1. If environment variable is present, use it. We don't expect
73 * the environment variable except for tests and other atypical setups.
74 * 2. <profile>/crashes/events
75 * 3. <UAppData>/Crash Reports/events
77 void SetUserAppDataDirectory(nsIFile
* aDir
);
78 void SetProfileDirectory(nsIFile
* aDir
);
79 void UpdateCrashEventsDir();
80 void SetMemoryReportFile(nsIFile
* aFile
);
81 nsresult
GetDefaultMemoryReportFile(nsIFile
** aFile
);
84 * Get the path where crash event files should be written.
86 bool GetCrashEventsDir(nsAString
& aPath
);
89 bool GetServerURL(nsACString
& aServerURL
);
90 nsresult
SetServerURL(const nsACString
& aServerURL
);
91 bool GetMinidumpPath(nsAString
& aPath
);
92 nsresult
SetMinidumpPath(const nsAString
& aPath
);
94 // These functions are thread safe and can be called in both the parent and
95 // child processes. Annotations added in the main process will be included in
96 // child process crashes too unless the child process sets its own annotations.
97 // If it does the child-provided annotation overrides the one set in the parent.
98 const bool* RegisterAnnotationBool(Annotation aKey
, const bool* aData
);
99 const uint32_t* RegisterAnnotationU32(Annotation aKey
, const uint32_t* aData
);
100 const uint64_t* RegisterAnnotationU64(Annotation aKey
, const uint64_t* aData
);
101 const size_t* RegisterAnnotationUSize(Annotation aKey
, const size_t* aData
);
102 const char* RegisterAnnotationCString(Annotation aKey
, const char* aData
);
103 const nsCString
* RegisterAnnotationNSCString(Annotation aKey
,
104 const nsCString
* aData
);
106 nsresult
RecordAnnotationBool(Annotation aKey
, bool aData
);
107 nsresult
RecordAnnotationU32(Annotation aKey
, uint32_t aData
);
108 nsresult
RecordAnnotationU64(Annotation aKey
, uint64_t aData
);
109 nsresult
RecordAnnotationUSize(Annotation aKey
, size_t aData
);
110 nsresult
RecordAnnotationCString(Annotation aKey
, const char* aData
);
111 nsresult
RecordAnnotationNSCString(Annotation aKey
, const nsACString
& aData
);
112 nsresult
RecordAnnotationNSString(Annotation aKey
, const nsAString
& aData
);
113 nsresult
UnrecordAnnotation(Annotation aKey
);
115 nsresult
AppendAppNotesToCrashReport(const nsACString
& data
);
117 // RAII class for setting a crash annotation during a limited scope of time.
118 // Will reset the named annotation to its previous value when destroyed.
120 // This type's behavior is identical to that of RecordAnnotation().
121 class MOZ_RAII AutoRecordAnnotation final
{
123 AutoRecordAnnotation(Annotation key
, bool data
);
124 AutoRecordAnnotation(Annotation key
, int data
);
125 AutoRecordAnnotation(Annotation key
, unsigned int data
);
126 AutoRecordAnnotation(Annotation key
, const nsACString
& data
);
127 ~AutoRecordAnnotation();
129 #ifdef MOZ_CRASHREPORTER
132 const nsCString mCurrent
;
133 const nsCString
* mPrevious
;
137 void AnnotateOOMAllocationSize(size_t size
);
138 void AnnotateTexturesSize(size_t size
);
139 nsresult
SetGarbageCollecting(bool collecting
);
140 void SetEventloopNestingLevel(uint32_t level
);
141 void SetMinidumpAnalysisAllThreads();
142 void ClearInactiveStateStart();
143 void SetInactiveStateStart();
145 nsresult
SetRestartArgs(int argc
, char** argv
);
146 nsresult
SetupExtraData(nsIFile
* aAppDataDirectory
, const nsACString
& aBuildID
);
147 // Registers an additional memory region to be included in the minidump
148 nsresult
RegisterAppMemory(void* ptr
, size_t length
);
149 nsresult
UnregisterAppMemory(void* ptr
);
151 // Include heap regions of the crash context.
152 void SetIncludeContextHeap(bool aValue
);
154 void GetAnnotation(uint32_t childPid
, Annotation annotation
,
157 // Functions for working with minidumps and .extras
158 typedef mozilla::EnumeratedArray
<Annotation
, nsCString
,
159 size_t(Annotation::Count
)>
161 void DeleteMinidumpFilesForID(
162 const nsAString
& aId
,
163 const Maybe
<nsString
>& aAdditionalMinidump
= Nothing());
164 bool GetMinidumpForID(const nsAString
& id
, nsIFile
** minidump
,
165 const Maybe
<nsString
>& aAdditionalMinidump
= Nothing());
166 bool GetIDFromMinidump(nsIFile
* minidump
, nsAString
& id
);
167 bool GetExtraFileForID(const nsAString
& id
, nsIFile
** extraFile
);
168 bool GetExtraFileForMinidump(nsIFile
* minidump
, nsIFile
** extraFile
);
169 bool WriteExtraFile(const nsAString
& id
, const AnnotationTable
& annotations
);
172 * Copies the non-empty annotations in the source table to the destination
173 * overwriting the corresponding entries.
175 void MergeCrashAnnotations(AnnotationTable
& aDst
, const AnnotationTable
& aSrc
);
178 nsresult
WriteMinidumpForException(EXCEPTION_POINTERS
* aExceptionInfo
);
181 bool WriteMinidumpForSigInfo(int signo
, siginfo_t
* info
, void* uc
);
184 nsresult
AppendObjCExceptionInfoToAppNotes(void* inException
);
186 nsresult
GetSubmitReports(bool* aSubmitReport
);
187 nsresult
SetSubmitReports(bool aSubmitReport
);
190 // This data is stored in the parent process, there is one copy for each child
191 // process. The mChildPid and mMinidumpFile fields are filled by the WER runtime
192 // exception module when the associated child process crashes.
193 struct WindowsErrorReportingData
{
194 // PID of the child process that crashed.
196 // Filename of the generated minidump; this is not a 0-terminated string
197 char mMinidumpFile
[40];
201 // Out-of-process crash reporter API.
203 // Initializes out-of-process crash reporting. This method must be called
204 // before the platform-specific notification pipe APIs are called. If called
205 // from off the main thread, this method will synchronously proxy to the main
209 // Return true if a dump was found for |childPid|, and return the
210 // path in |dump|. The caller owns the last reference to |dump| if it
211 // is non-nullptr. The annotations for the crash will be stored in
212 // |aAnnotations|. The sequence parameter will be filled with an ordinal
213 // indicating which remote process crashed first.
214 bool TakeMinidumpForChild(uint32_t childPid
, nsIFile
** dump
,
215 AnnotationTable
& aAnnotations
,
216 uint32_t* aSequence
= nullptr);
219 * If a dump was found for |childPid| then write a minimal .extra file to
220 * complete it and remove it from the list of pending crash dumps. It's
221 * required to call this method after a non-main process crash if the crash
222 * report could not be finalized via the CrashReporterHost (for example because
223 * it wasn't instanced yet).
225 * @param aChildPid The pid of the crashed child process
226 * @param aType The type of the crashed process
227 * @param aDumpId A string that will be filled with the dump ID
229 [[nodiscard
]] bool FinalizeOrphanedMinidump(uint32_t aChildPid
,
230 GeckoProcessType aType
,
231 nsString
* aDumpId
= nullptr);
234 typedef HANDLE ProcessHandle
;
235 typedef DWORD ProcessId
;
236 typedef DWORD ThreadId
;
237 typedef HANDLE FileHandle
;
238 const FileHandle kInvalidFileHandle
= INVALID_HANDLE_VALUE
;
239 #elif defined(XP_MACOSX)
240 typedef task_t ProcessHandle
;
241 typedef pid_t ProcessId
;
242 typedef mach_port_t ThreadId
;
243 typedef int FileHandle
;
244 const FileHandle kInvalidFileHandle
= -1;
246 typedef int ProcessHandle
;
247 typedef pid_t ProcessId
;
248 typedef int ThreadId
;
249 typedef int FileHandle
;
250 const FileHandle kInvalidFileHandle
= -1;
253 // Return the current thread's ID.
255 // XXX: this is a somewhat out-of-place interface to expose through
256 // crashreporter, but it takes significant work to call sys_gettid()
257 // correctly on Linux and breakpad has already jumped through those
259 ThreadId
CurrentThreadId();
262 * Take a minidump of the target process and pair it with a new minidump of the
263 * calling process and thread. The caller will own both dumps after this call.
264 * If this function fails it will attempt to delete any files that were created.
266 * The .extra information created will not include an 'additional_minidumps'
269 * @param aTargetPid The target process for the minidump.
270 * @param aTargetBlamedThread The target thread for the minidump.
271 * @param aIncomingPairName The name to apply to the paired dump the caller
273 * @param aTargetDumpOut The target minidump file paired up with the new one.
274 * @param aTargetAnnotations The crash annotations of the target process.
275 * @return bool indicating success or failure
277 bool CreateMinidumpsAndPair(ProcessHandle aTargetPid
,
278 ThreadId aTargetBlamedThread
,
279 const nsACString
& aIncomingPairName
,
280 AnnotationTable
& aTargetAnnotations
,
281 nsIFile
** aTargetDumpOut
);
283 #if defined(XP_WIN) || defined(XP_MACOSX)
284 // Parent-side API for children
285 const char* GetChildNotificationPipe();
287 # ifdef MOZ_CRASHREPORTER_INJECTOR
288 // Inject a crash report client into an arbitrary process, and inform the
289 // callback object when it crashes. Parent process only.
291 class InjectorCrashCallback
{
293 InjectorCrashCallback() {}
296 * Inform the callback of a crash. The client code should call
297 * TakeMinidumpForChild to remove it from the PID mapping table.
299 * The callback will not be fired if the client has already called
300 * TakeMinidumpForChild for this process ID.
302 virtual void OnCrash(DWORD processID
) = 0;
305 // This method implies OOPInit
306 void InjectCrashReporterIntoProcess(DWORD processID
, InjectorCrashCallback
* cb
);
307 void UnregisterInjectorCallback(DWORD processID
);
310 // Parent-side API for children
312 // Set the outparams for crash reporter server's fd (|childCrashFd|)
313 // and the magic fd number it should be remapped to
314 // (|childCrashRemapFd|) before exec() in the child process.
315 // |SetRemoteExceptionHandler()| in the child process expects to find
316 // the server at |childCrashRemapFd|. Return true if successful.
318 // If crash reporting is disabled, both outparams will be set to -1
319 // and |true| will be returned.
320 bool CreateNotificationPipeForChild(int* childCrashFd
, int* childCrashRemapFd
);
325 bool SetRemoteExceptionHandler(const char* aCrashPipe
= nullptr);
326 bool UnsetRemoteExceptionHandler(bool wasSet
= true);
328 #if defined(MOZ_WIDGET_ANDROID)
329 // Android creates child process as services so we must explicitly set
330 // the handle for the pipe since it can't get remapped to a default value.
331 void SetNotificationPipeForChild(FileHandle childCrashFd
);
334 } // namespace CrashReporter
336 #endif /* nsExceptionHandler_h__ */