/src/mozilla-central/mfbt/Assertions.cpp
Line | Count | Source (jump to first uncovered line) |
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 file, |
4 | | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
5 | | |
6 | | #include "mozilla/Assertions.h" |
7 | | #include "mozilla/Atomics.h" |
8 | | |
9 | | #include <stdarg.h> |
10 | | |
11 | | MOZ_BEGIN_EXTERN_C |
12 | | |
13 | | /* |
14 | | * The crash reason is defined as a global variable here rather than in the |
15 | | * crash reporter itself to make it available to all code, even libraries like |
16 | | * JS that don't link with the crash reporter directly. This value will only |
17 | | * be consumed if the crash reporter is used by the target application. |
18 | | */ |
19 | | MFBT_DATA const char* gMozCrashReason = nullptr; |
20 | | |
21 | | #ifndef DEBUG |
22 | | MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void |
23 | | MOZ_CrashOOL(int aLine, const char* aReason) |
24 | | #else |
25 | | MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE void |
26 | | MOZ_CrashOOL(const char* aFilename, int aLine, const char* aReason) |
27 | | #endif |
28 | 0 | { |
29 | | #ifdef DEBUG |
30 | | MOZ_ReportCrash(aReason, aFilename, aLine); |
31 | | #endif |
32 | | gMozCrashReason = aReason; |
33 | 0 | MOZ_REALLY_CRASH(aLine); |
34 | 0 | } |
35 | | |
36 | | static char sPrintfCrashReason[sPrintfCrashReasonSize] = {}; |
37 | | |
38 | | // Accesses to this atomic are not included in web replay recordings, so that |
39 | | // if we crash in an area where recorded events are not allowed the true reason |
40 | | // for the crash is not obscured by a record/replay error. |
41 | | static mozilla::Atomic<bool, mozilla::SequentiallyConsistent, |
42 | | mozilla::recordreplay::Behavior::DontPreserve> sCrashing(false); |
43 | | |
44 | | #ifndef DEBUG |
45 | | MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(2, 3) void |
46 | | MOZ_CrashPrintf(int aLine, const char* aFormat, ...) |
47 | | #else |
48 | | MFBT_API MOZ_COLD MOZ_NORETURN MOZ_NEVER_INLINE MOZ_FORMAT_PRINTF(3, 4) void |
49 | | MOZ_CrashPrintf(const char* aFilename, int aLine, const char* aFormat, ...) |
50 | | #endif |
51 | 0 | { |
52 | 0 | if (!sCrashing.compareExchange(false, true)) { |
53 | 0 | // In the unlikely event of a race condition, skip |
54 | 0 | // setting the crash reason and just crash safely. |
55 | 0 | MOZ_REALLY_CRASH(aLine); |
56 | 0 | } |
57 | 0 | va_list aArgs; |
58 | 0 | va_start(aArgs, aFormat); |
59 | 0 | int ret = vsnprintf(sPrintfCrashReason, sPrintfCrashReasonSize, |
60 | 0 | aFormat, aArgs); |
61 | 0 | va_end(aArgs); |
62 | 0 | MOZ_RELEASE_ASSERT(ret >= 0 && size_t(ret) < sPrintfCrashReasonSize, |
63 | 0 | "Could not write the explanation string to the supplied buffer!"); |
64 | | #ifdef DEBUG |
65 | | MOZ_ReportCrash(sPrintfCrashReason, aFilename, aLine); |
66 | | #endif |
67 | 0 | gMozCrashReason = sPrintfCrashReason; |
68 | 0 | MOZ_REALLY_CRASH(aLine); |
69 | 0 | } |
70 | | |
71 | | MOZ_END_EXTERN_C |