mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-01-22 19:01:05 +00:00
Add first chance exception handler API
This change adds the option for Breakpad hosts to register a callback that gets the first chance to handle an exception. The handler will return true if it handled the exception and false otherwise. The primary use case is V8's trap-based bounds checking support for WebAssembly. Bug: Change-Id: I5aa5b87d1229f1cef905a00404fa2027ee86be56 Reviewed-on: https://chromium-review.googlesource.com/509994 Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
parent
c142362a6c
commit
1628d99f7b
|
@ -218,6 +218,7 @@ pthread_mutex_t g_handler_stack_mutex_ = PTHREAD_MUTEX_INITIALIZER;
|
|||
// time can use |g_crash_context_|.
|
||||
ExceptionHandler::CrashContext g_crash_context_;
|
||||
|
||||
FirstChanceHandler g_first_chance_handler_ = nullptr;
|
||||
} // namespace
|
||||
|
||||
// Runs before crashing: normal context.
|
||||
|
@ -331,6 +332,18 @@ void ExceptionHandler::RestoreHandlersLocked() {
|
|||
// Runs on the crashing thread.
|
||||
// static
|
||||
void ExceptionHandler::SignalHandler(int sig, siginfo_t* info, void* uc) {
|
||||
|
||||
// Give the first chance handler a chance to recover from this signal
|
||||
//
|
||||
// This is primarily used by V8. V8 uses guard regions to guarantee memory
|
||||
// safety in WebAssembly. This means some signals might be expected if they
|
||||
// originate from Wasm code while accessing the guard region. We give V8 the
|
||||
// chance to handle and recover from these signals first.
|
||||
if (g_first_chance_handler_ != nullptr &&
|
||||
g_first_chance_handler_(sig, info, uc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// All the exception signals are blocked at this point.
|
||||
pthread_mutex_lock(&g_handler_stack_mutex_);
|
||||
|
||||
|
@ -782,4 +795,8 @@ bool ExceptionHandler::WriteMinidumpForChild(pid_t child,
|
|||
return callback ? callback(descriptor, callback_context, true) : true;
|
||||
}
|
||||
|
||||
void SetFirstChanceExceptionHandler(FirstChanceHandler callback) {
|
||||
g_first_chance_handler_ = callback;
|
||||
}
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
|
|
@ -273,6 +273,10 @@ class ExceptionHandler {
|
|||
AppMemoryList app_memory_list_;
|
||||
};
|
||||
|
||||
|
||||
typedef bool (*FirstChanceHandler)(int, void*, void*);
|
||||
void SetFirstChanceExceptionHandler(FirstChanceHandler callback);
|
||||
|
||||
} // namespace google_breakpad
|
||||
|
||||
#endif // CLIENT_LINUX_HANDLER_EXCEPTION_HANDLER_H_
|
||||
|
|
|
@ -1177,3 +1177,26 @@ TEST(ExceptionHandlerTest, WriteMinidumpForChild) {
|
|||
close(fds[1]);
|
||||
unlink(minidump_filename.c_str());
|
||||
}
|
||||
|
||||
namespace {
|
||||
const int kSimpleFirstChanceReturnStatus = 42;
|
||||
bool SimpleFirstChanceHandler(int, void*, void*) {
|
||||
exit(kSimpleFirstChanceReturnStatus);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ExceptionHandlerTest, FirstChanceHandlerRuns) {
|
||||
AutoTempDir temp_dir;
|
||||
|
||||
const pid_t child = fork();
|
||||
if (child == 0) {
|
||||
ExceptionHandler handler(
|
||||
MinidumpDescriptor(temp_dir.path()), NULL, NULL, NULL, true, -1);
|
||||
google_breakpad::SetFirstChanceExceptionHandler(SimpleFirstChanceHandler);
|
||||
DoNullPointerDereference();
|
||||
}
|
||||
int status;
|
||||
ASSERT_NE(HANDLE_EINTR(waitpid(child, &status, 0)), -1);
|
||||
ASSERT_TRUE(WIFEXITED(status));
|
||||
ASSERT_EQ(kSimpleFirstChanceReturnStatus, WEXITSTATUS(status));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue