mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-28 07:48:14 +08:00
linux: re-order first-chance-handlers, and disabled signal handlers
Both running first chance handlers and checking for disabled signal handlers should no longer interact with DumpWithoutCrashing(). First-chance-handlers should also run even with disabled crashpad signal handlers or else those signals would be reported by the next chained signal handlers as crashes. Change-Id: I64b3da42c400a1c431c6228d4da181ed56bfda89 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3403413 Reviewed-by: Mark Mentovai <mark@chromium.org> Commit-Queue: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
1721bb991c
commit
667424894f
@ -421,7 +421,7 @@ class CrashpadClient {
|
|||||||
//! CaptureContext() or similar.
|
//! CaptureContext() or similar.
|
||||||
static void DumpWithoutCrash(NativeCPUContext* context);
|
static void DumpWithoutCrash(NativeCPUContext* context);
|
||||||
|
|
||||||
//! \brief Disables any installed crash handler, including any
|
//! \brief Disables any installed crash handler, not including any
|
||||||
//! FirstChanceHandler and crashes the current process.
|
//! FirstChanceHandler and crashes the current process.
|
||||||
//!
|
//!
|
||||||
//! \param[in] message A message to be logged before crashing.
|
//! \param[in] message A message to be logged before crashing.
|
||||||
|
@ -148,17 +148,7 @@ class SignalHandler {
|
|||||||
|
|
||||||
// The base implementation for all signal handlers, suitable for calling
|
// The base implementation for all signal handlers, suitable for calling
|
||||||
// directly to simulate signal delivery.
|
// directly to simulate signal delivery.
|
||||||
bool HandleCrash(int signo, siginfo_t* siginfo, void* context) {
|
void HandleCrash(int signo, siginfo_t* siginfo, void* context) {
|
||||||
if (disabled_for_thread_) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (first_chance_handler_ &&
|
|
||||||
first_chance_handler_(
|
|
||||||
signo, siginfo, static_cast<ucontext_t*>(context))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
exception_information_.siginfo_address =
|
exception_information_.siginfo_address =
|
||||||
FromPointerCast<decltype(exception_information_.siginfo_address)>(
|
FromPointerCast<decltype(exception_information_.siginfo_address)>(
|
||||||
siginfo);
|
siginfo);
|
||||||
@ -169,7 +159,6 @@ class SignalHandler {
|
|||||||
|
|
||||||
ScopedPrSetDumpable set_dumpable(false);
|
ScopedPrSetDumpable set_dumpable(false);
|
||||||
HandleCrashImpl();
|
HandleCrashImpl();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -198,9 +187,16 @@ class SignalHandler {
|
|||||||
static void HandleOrReraiseSignal(int signo,
|
static void HandleOrReraiseSignal(int signo,
|
||||||
siginfo_t* siginfo,
|
siginfo_t* siginfo,
|
||||||
void* context) {
|
void* context) {
|
||||||
if (handler_->HandleCrash(signo, siginfo, context)) {
|
if (handler_->first_chance_handler_ &&
|
||||||
|
handler_->first_chance_handler_(
|
||||||
|
signo, siginfo, static_cast<ucontext_t*>(context))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!handler_->disabled_for_thread_) {
|
||||||
|
handler_->HandleCrash(signo, siginfo, context);
|
||||||
|
}
|
||||||
|
|
||||||
Signals::RestoreHandlerAndReraiseSignalOnReturn(
|
Signals::RestoreHandlerAndReraiseSignalOnReturn(
|
||||||
siginfo, handler_->old_actions_.ActionForSignal(signo));
|
siginfo, handler_->old_actions_.ActionForSignal(signo));
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "client/crashpad_client.h"
|
#include "client/crashpad_client.h"
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
#include <setjmp.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
@ -108,10 +109,6 @@ class StartHandlerForSelfTest
|
|||||||
StartHandlerForSelfTestOptions options_;
|
StartHandlerForSelfTestOptions options_;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool HandleCrashSuccessfully(int, siginfo_t*, ucontext_t*) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool InstallHandler(CrashpadClient* client,
|
bool InstallHandler(CrashpadClient* client,
|
||||||
bool start_at_crash,
|
bool start_at_crash,
|
||||||
const base::FilePath& handler_path,
|
const base::FilePath& handler_path,
|
||||||
@ -222,13 +219,21 @@ int RecurseInfinitely(int* ptr) {
|
|||||||
}
|
}
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
sigjmp_buf do_crash_sigjmp_env;
|
||||||
|
|
||||||
|
bool HandleCrashSuccessfully(int, siginfo_t*, ucontext_t*) {
|
||||||
|
siglongjmp(do_crash_sigjmp_env, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void DoCrash(const StartHandlerForSelfTestOptions& options,
|
void DoCrash(const StartHandlerForSelfTestOptions& options,
|
||||||
CrashpadClient* client) {
|
CrashpadClient* client) {
|
||||||
|
if (sigsetjmp(do_crash_sigjmp_env, 1) != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (options.crash_type) {
|
switch (options.crash_type) {
|
||||||
case CrashType::kSimulated:
|
case CrashType::kSimulated:
|
||||||
if (options.set_first_chance_handler) {
|
|
||||||
client->SetFirstChanceExceptionHandler(HandleCrashSuccessfully);
|
|
||||||
}
|
|
||||||
CRASHPAD_SIMULATE_CRASH();
|
CRASHPAD_SIMULATE_CRASH();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -364,6 +369,10 @@ CRASHPAD_CHILD_TEST_MAIN(StartHandlerForSelfTestChild) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.set_first_chance_handler) {
|
||||||
|
client.SetFirstChanceExceptionHandler(HandleCrashSuccessfully);
|
||||||
|
}
|
||||||
|
|
||||||
#if BUILDFLAG(IS_ANDROID)
|
#if BUILDFLAG(IS_ANDROID)
|
||||||
if (android_set_abort_message) {
|
if (android_set_abort_message) {
|
||||||
android_set_abort_message(kTestAbortMessage);
|
android_set_abort_message(kTestAbortMessage);
|
||||||
@ -386,6 +395,7 @@ class StartHandlerForSelfInChildTest : public MultiprocessExec {
|
|||||||
StartHandlerForSelfInChildTest(const StartHandlerForSelfTestOptions& options)
|
StartHandlerForSelfInChildTest(const StartHandlerForSelfTestOptions& options)
|
||||||
: MultiprocessExec(), options_(options) {
|
: MultiprocessExec(), options_(options) {
|
||||||
SetChildTestMainFunction("StartHandlerForSelfTestChild");
|
SetChildTestMainFunction("StartHandlerForSelfTestChild");
|
||||||
|
if (!options.set_first_chance_handler) {
|
||||||
switch (options.crash_type) {
|
switch (options.crash_type) {
|
||||||
case CrashType::kSimulated:
|
case CrashType::kSimulated:
|
||||||
// kTerminationNormal, EXIT_SUCCESS
|
// kTerminationNormal, EXIT_SUCCESS
|
||||||
@ -399,6 +409,7 @@ class StartHandlerForSelfInChildTest : public MultiprocessExec {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StartHandlerForSelfInChildTest(const StartHandlerForSelfInChildTest&) =
|
StartHandlerForSelfInChildTest(const StartHandlerForSelfInChildTest&) =
|
||||||
delete;
|
delete;
|
||||||
@ -447,9 +458,12 @@ class StartHandlerForSelfInChildTest : public MultiprocessExec {
|
|||||||
reports.clear();
|
reports.clear();
|
||||||
ASSERT_EQ(database->GetPendingReports(&reports),
|
ASSERT_EQ(database->GetPendingReports(&reports),
|
||||||
CrashReportDatabase::kNoError);
|
CrashReportDatabase::kNoError);
|
||||||
ASSERT_EQ(reports.size(), options_.set_first_chance_handler ? 0u : 1u);
|
|
||||||
|
|
||||||
if (options_.set_first_chance_handler) {
|
bool report_expected = !options_.set_first_chance_handler ||
|
||||||
|
options_.crash_type == CrashType::kSimulated;
|
||||||
|
ASSERT_EQ(reports.size(), report_expected ? 1u : 0u);
|
||||||
|
|
||||||
|
if (!report_expected) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,11 +477,6 @@ class StartHandlerForSelfInChildTest : public MultiprocessExec {
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST_P(StartHandlerForSelfTest, StartHandlerInChild) {
|
TEST_P(StartHandlerForSelfTest, StartHandlerInChild) {
|
||||||
if (Options().set_first_chance_handler &&
|
|
||||||
Options().crash_type != CrashType::kSimulated) {
|
|
||||||
// TODO(jperaza): test first chance handlers with real crashes.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
|
#if defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER) || \
|
||||||
defined(UNDEFINED_SANITIZER)
|
defined(UNDEFINED_SANITIZER)
|
||||||
if (Options().crash_type == CrashType::kInfiniteRecursion) {
|
if (Options().crash_type == CrashType::kInfiniteRecursion) {
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "util/linux/traits.h"
|
#include "util/linux/traits.h"
|
||||||
#include "util/misc/reinterpret_bytes.h"
|
#include "util/misc/reinterpret_bytes.h"
|
||||||
#include "util/numeric/safe_assignment.h"
|
#include "util/numeric/safe_assignment.h"
|
||||||
|
#include "util/posix/signals.h"
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -445,6 +446,9 @@ bool ExceptionSnapshotLinux::ReadSiginfo(ProcessReaderLinux* reader,
|
|||||||
PUSH_CODE(siginfo.sigval.sigval);
|
PUSH_CODE(siginfo.sigval.sigval);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Signals::kSimulatedSigno:
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG(WARNING) << "Unhandled signal " << siginfo.signo;
|
LOG(WARNING) << "Unhandled signal " << siginfo.signo;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user