From 193041c2651a9aeb7f5b3b7f93e9b89b57b67df8 Mon Sep 17 00:00:00 2001 From: satyam Date: Thu, 20 Aug 2020 13:13:10 -0700 Subject: [PATCH] Log address at which fault occurred in FailureSignalHandler. --- absl/debugging/failure_signal_handler.cc | 28 +++++++++++++------ absl/debugging/failure_signal_handler_test.cc | 24 ++++++++++------ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/absl/debugging/failure_signal_handler.cc b/absl/debugging/failure_signal_handler.cc index 5d13bdbbbd1..54d91bfd1ec 100644 --- a/absl/debugging/failure_signal_handler.cc +++ b/absl/debugging/failure_signal_handler.cc @@ -219,14 +219,22 @@ static void WriteToStderr(const char* data) { absl::raw_logging_internal::SafeWriteToStderr(data, strlen(data)); } -static void WriteSignalMessage(int signo, void (*writerfn)(const char*)) { +static void WriteSignalMessage(int signo, siginfo_t* siginfo, + void (*writerfn)(const char*)) { char buf[64]; const char* const signal_string = debugging_internal::FailureSignalToString(signo); if (signal_string != nullptr && signal_string[0] != '\0') { - snprintf(buf, sizeof(buf), "*** %s received at time=%ld ***\n", - signal_string, - static_cast(time(nullptr))); // NOLINT(runtime/int) + if (siginfo == nullptr) { + snprintf(buf, sizeof(buf), "*** %s received at time=%ld ***\n", + signal_string, + static_cast(time(nullptr))); // NOLINT(runtime/int) + } else { + snprintf(buf, sizeof(buf), "*** %s (0x%lx) received at time=%ld ***\n", + signal_string, + reinterpret_cast(siginfo->si_addr), + static_cast(time(nullptr))); // NOLINT(runtime/int) + } } else { snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld ***\n", signo, static_cast(time(nullptr))); // NOLINT(runtime/int) @@ -269,10 +277,10 @@ ABSL_ATTRIBUTE_NOINLINE static void WriteStackTrace( // Called by AbslFailureSignalHandler() to write the failure info. It is // called once with writerfn set to WriteToStderr() and then possibly // with writerfn set to the user provided function. -static void WriteFailureInfo(int signo, void* ucontext, +static void WriteFailureInfo(int signo, siginfo_t* siginfo, void* ucontext, void (*writerfn)(const char*)) { WriterFnStruct writerfn_struct{writerfn}; - WriteSignalMessage(signo, writerfn); + WriteSignalMessage(signo, siginfo, writerfn); WriteStackTrace(ucontext, fsh_options.symbolize_stacktrace, WriterFnWrapper, &writerfn_struct); } @@ -310,8 +318,10 @@ ABSL_CONST_INIT static std::atomic failed_tid(0); #ifndef ABSL_HAVE_SIGACTION static void AbslFailureSignalHandler(int signo) { void* ucontext = nullptr; + siginfo_t* siginfo = nullptr; #else -static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) { +static void AbslFailureSignalHandler(int signo, siginfo_t* siginfo, + void* ucontext) { #endif const GetTidType this_tid = absl::base_internal::GetTID(); @@ -344,12 +354,12 @@ static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) { #endif // First write to stderr. - WriteFailureInfo(signo, ucontext, WriteToStderr); + WriteFailureInfo(signo, siginfo, ucontext, WriteToStderr); // Riskier code (because it is less likely to be async-signal-safe) // goes after this point. if (fsh_options.writerfn != nullptr) { - WriteFailureInfo(signo, ucontext, fsh_options.writerfn); + WriteFailureInfo(signo, siginfo, ucontext, fsh_options.writerfn); } if (fsh_options.call_previous_handler) { diff --git a/absl/debugging/failure_signal_handler_test.cc b/absl/debugging/failure_signal_handler_test.cc index d8283b2f47c..fabaf51818b 100644 --- a/absl/debugging/failure_signal_handler_test.cc +++ b/absl/debugging/failure_signal_handler_test.cc @@ -47,13 +47,17 @@ void InstallHandlerAndRaise(int signo) { TEST_P(FailureSignalHandlerDeathTest, AbslFailureSignal) { const int signo = GetParam(); - std::string exit_regex = absl::StrCat( - "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo), - " received at time="); #ifndef _WIN32 + std::string exit_regex = absl::StrCat( + "\\*\\*\\* ", + absl::debugging_internal::FailureSignalToString(signo), + " \\(0x[0-9a-f]+\\) received at time="); EXPECT_EXIT(InstallHandlerAndRaise(signo), testing::KilledBySignal(signo), exit_regex); #else + std::string exit_regex = absl::StrCat( + "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo), + " received at time="); // Windows doesn't have testing::KilledBySignal(). EXPECT_DEATH_IF_SUPPORTED(InstallHandlerAndRaise(signo), exit_regex); #endif @@ -99,13 +103,17 @@ TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) { std::string tmp_dir = GetTmpDir(); std::string file = absl::StrCat(tmp_dir, "/signo_", signo); - std::string exit_regex = absl::StrCat( - "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo), - " received at time="); #ifndef _WIN32 + std::string exit_regex = absl::StrCat( + "\\*\\*\\* ", + absl::debugging_internal::FailureSignalToString(signo), + " \\(0x[0-9a-f]+\\) received at time="); EXPECT_EXIT(InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo), testing::KilledBySignal(signo), exit_regex); #else + std::string exit_regex = absl::StrCat( + "\\*\\*\\* ", absl::debugging_internal::FailureSignalToString(signo), + " received at time="); // Windows doesn't have testing::KilledBySignal(). EXPECT_DEATH_IF_SUPPORTED( InstallHandlerWithWriteToFileAndRaise(file.c_str(), signo), exit_regex); @@ -116,11 +124,11 @@ TEST_P(FailureSignalHandlerDeathTest, AbslFatalSignalsWithWriterFn) { ASSERT_TRUE(error_output.is_open()) << file; std::string error_line; std::getline(error_output, error_line); + // TODO: Is it recommended to use std::regex within absl? EXPECT_THAT( error_line, StartsWith(absl::StrCat( - "*** ", absl::debugging_internal::FailureSignalToString(signo), - " received at "))); + "*** ", absl::debugging_internal::FailureSignalToString(signo)))); if (absl::debugging_internal::StackTraceWorksForTest()) { std::getline(error_output, error_line);