Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(718)

Unified Diff: third_party/crashpad/crashpad/handler/handler_main.cc

Issue 2679313002: Update Crashpad to 88442dd5788bf7836ab013939cca4a4683560cb0 (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/crashpad/crashpad/DEPS ('k') | third_party/crashpad/crashpad/snapshot/mac/process_types.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/crashpad/crashpad/handler/handler_main.cc
diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc
index 3ada8c3e50567990378061214fe03252783f5edf..9433a6af5186ec33ebf6c68fb17948adb227381d 100644
--- a/third_party/crashpad/crashpad/handler/handler_main.cc
+++ b/third_party/crashpad/crashpad/handler/handler_main.cc
@@ -14,9 +14,11 @@
#include "handler/handler_main.h"
+#include <errno.h>
#include <getopt.h>
#include <stdint.h>
#include <stdlib.h>
+#include <sys/types.h>
#include <map>
#include <memory>
@@ -38,6 +40,8 @@
#include "handler/prune_crash_reports_thread.h"
#include "tools/tool_support.h"
#include "util/file/file_io.h"
+#include "util/misc/metrics.h"
+#include "util/numeric/in_range_cast.h"
#include "util/stdlib/map_insert.h"
#include "util/stdlib/string_number_conversion.h"
#include "util/string/split_string.h"
@@ -105,6 +109,122 @@ void Usage(const base::FilePath& me) {
#if defined(OS_MACOSX)
+struct sigaction g_original_crash_sigaction[NSIG];
+
+void HandleCrashSignal(int sig, siginfo_t* siginfo, void* context) {
+ // Is siginfo->si_code useful? The only interesting values on macOS are 0 (not
+ // useful, signals generated asynchronously such as by kill() or raise()) and
+ // small positive numbers (useful, signal generated via a hardware fault). The
+ // standard specifies these other constants, and while xnu never uses them,
+ // they are intended to denote signals generated asynchronously and are
+ // included here. Additionally, existing practice on other systems
+ // (acknowledged by the standard) is for negative numbers to indicate that a
+ // signal was generated asynchronously. Although xnu does not do this, allow
+ // for the possibility for completeness.
+ bool si_code_valid = !(siginfo->si_code <= 0 ||
+ siginfo->si_code == SI_USER ||
+ siginfo->si_code == SI_QUEUE ||
+ siginfo->si_code == SI_TIMER ||
+ siginfo->si_code == SI_ASYNCIO ||
+ siginfo->si_code == SI_MESGQ);
+
+ // 0x5343 = 'SC', signifying “signal and code”, disambiguates from the schema
+ // used by ExceptionCodeForMetrics(). That system primarily uses Mach
+ // exception types and codes, which are not available to a POSIX signal
+ // handler. It does provide a way to encode only signal numbers, but does so
+ // with the understanding that certain “raw” signals would not be encountered
+ // without a Mach exception. Furthermore, it does not allow siginfo->si_code
+ // to be encoded, because that’s not available to Mach exception handlers. It
+ // would be a shame to lose that information available to a POSIX signal
+ // handler.
+ int metrics_code = 0x53430000 | (InRangeCast<uint8_t>(sig, 0xff) << 8);
+ if (si_code_valid) {
+ metrics_code |= InRangeCast<uint8_t>(siginfo->si_code, 0xff);
+ }
+ Metrics::HandlerCrashed(metrics_code);
+
+ // Restore the previous signal handler.
+ DCHECK_GT(sig, 0);
+ DCHECK_LT(static_cast<size_t>(sig), arraysize(g_original_crash_sigaction));
+ struct sigaction* osa = &g_original_crash_sigaction[sig];
+ int rv = sigaction(sig, osa, nullptr);
+ DPLOG_IF(ERROR, rv != 0) << "sigaction " << sig;
+
+ // If the signal was received synchronously resulting from a hardware fault,
+ // returning from the signal handler will cause the kernel to re-raise it,
+ // because this handler hasn’t done anything to alleviate the condition that
+ // caused the signal to be raised in the first place. With the old signal
+ // handler in place (expected to be SIG_DFL), it will cause the same behavior
+ // to be taken as though this signal handler had never been installed at all
+ // (expected to be a crash). This is ideal, because the signal is re-raised
+ // with the same properties and from the same context that initially triggered
+ // it, providing the best debugging experience.
+
+ if ((sig != SIGILL && sig != SIGFPE && sig != SIGBUS && sig != SIGSEGV) ||
+ !si_code_valid) {
+ // Signals received other than via hardware faults, such as those raised
+ // asynchronously via kill() and raise(), and those arising via hardware
+ // traps such as int3 (resulting in SIGTRAP but advancing the instruction
+ // pointer), will not reoccur on their own when returning from the signal
+ // handler. Re-raise them or call to the previous signal handler as
+ // appropriate.
+ //
+ // Unfortunately, when SIGBUS is received asynchronously via kill(),
+ // siginfo->si_code makes it appear as though it was actually received via a
+ // hardware fault. See 10.12.3 xnu-3789.41.3/bsd/dev/i386/unix_signal.c
+ // sendsig(). An asynchronous SIGBUS will thus cause the handler-crashed
+ // metric to be logged but will not cause the process to terminate. This
+ // isn’t ideal, but asynchronous SIGBUS is an unexpected condition. The
+ // alternative, to re-raise here on any SIGBUS, is a bad idea because it
+ // would lose properties associated with the the original signal, which are
+ // very valuable for debugging and are visible to a Mach exception handler.
+ // Since SIGBUS is normally received synchronously in response to a hardware
+ // fault, don’t sweat the unexpected asynchronous case.
+ if (osa->sa_handler == SIG_DFL) {
+ // Because this signal handler executes with the signal blocked, this
+ // raise() cannot immediately deliver the signal. Delivery is deferred
+ // until this signal handler returns and the signal becomes unblocked. The
+ // re-raised signal will appear with the same context as where it was
+ // initially triggered.
+ rv = raise(sig);
+ DPLOG_IF(ERROR, rv != 0) << "raise";
+ } else if (osa->sa_handler != SIG_IGN) {
+ if (osa->sa_flags & SA_SIGINFO) {
+ osa->sa_sigaction(sig, siginfo, context);
+ } else {
+ osa->sa_handler(sig);
+ }
+ }
+ }
+}
+
+void InstallCrashHandler() {
+ struct sigaction sa = {};
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = HandleCrashSignal;
+
+ // These are the core-generating signals from 10.12.3
+ // xnu-3789.41.3/bsd/sys/signalvar.h sigprop: entries with SA_CORE are in the
+ // set.
+ const int kSignals[] = {SIGQUIT,
+ SIGILL,
+ SIGTRAP,
+ SIGABRT,
+ SIGEMT,
+ SIGFPE,
+ SIGBUS,
+ SIGSEGV,
+ SIGSYS};
+
+ for (int sig : kSignals) {
+ DCHECK_GT(sig, 0);
+ DCHECK_LT(static_cast<size_t>(sig), arraysize(g_original_crash_sigaction));
+ int rv = sigaction(sig, &sa, &g_original_crash_sigaction[sig]);
+ PCHECK(rv == 0) << "sigaction " << sig;
+ }
+}
+
struct ResetSIGTERMTraits {
static struct sigaction* InvalidValue() {
return nullptr;
@@ -126,9 +246,8 @@ void HandleSIGTERM(int sig, siginfo_t* siginfo, void* context) {
g_exception_handler_server->Stop();
}
-#endif // OS_MACOSX
+#elif defined(OS_WIN)
-#if defined(OS_WIN)
LONG(WINAPI* g_original_exception_filter)(EXCEPTION_POINTERS*) = nullptr;
LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) {
@@ -139,15 +258,18 @@ LONG WINAPI UnhandledExceptionHandler(EXCEPTION_POINTERS* exception_pointers) {
else
return EXCEPTION_CONTINUE_SEARCH;
}
-#endif // OS_WIN
+
+void InstallCrashHandler() {
+ g_original_exception_filter =
+ SetUnhandledExceptionFilter(&UnhandledExceptionHandler);
+}
+
+#endif // OS_MACOSX
} // namespace
int HandlerMain(int argc, char* argv[]) {
-#if defined(OS_WIN)
- g_original_exception_filter =
- SetUnhandledExceptionFilter(&UnhandledExceptionHandler);
-#endif
+ InstallCrashHandler();
const base::FilePath argv0(
ToolSupport::CommandLineArgumentToFilePathStringType(argv[0]));
« no previous file with comments | « third_party/crashpad/crashpad/DEPS ('k') | third_party/crashpad/crashpad/snapshot/mac/process_types.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698