Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log address at which fault occurred in FailureSignalHandler. #772

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions absl/debugging/failure_signal_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<long>(time(nullptr))); // NOLINT(runtime/int)
if (siginfo == nullptr) {
snprintf(buf, sizeof(buf), "*** %s received at time=%ld ***\n",
signal_string,
static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
} else {
snprintf(buf, sizeof(buf), "*** %s (0x%lx) received at time=%ld ***\n",
signal_string,
reinterpret_cast<uintptr_t>(siginfo->si_addr),
static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
}
} else {
snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld ***\n",
signo, static_cast<long>(time(nullptr))); // NOLINT(runtime/int)
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -310,8 +318,10 @@ ABSL_CONST_INIT static std::atomic<GetTidType> 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();
Expand Down Expand Up @@ -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) {
Expand Down
24 changes: 16 additions & 8 deletions absl/debugging/failure_signal_handler_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down