diff options
author | 2018-03-30 18:36:09 +0000 | |
---|---|---|
committer | 2018-03-30 18:36:09 +0000 | |
commit | 50c2668b11c3adbd62cc852460bf867b20329e95 (patch) | |
tree | bb50d00ff0890c2e10f351f462b47b56b01e78ea | |
parent | 846bcc010dc76b3bae8d79d62cf2f83cdaa28e0f (diff) | |
parent | cdd53140b77bf724a4d7451d4b495dbd90875372 (diff) |
Merge "ART: Experiment with timeout dumping"
-rw-r--r-- | runtime/runtime_common.cc | 94 |
1 files changed, 70 insertions, 24 deletions
diff --git a/runtime/runtime_common.cc b/runtime/runtime_common.cc index 59af9187f9..eae2505ce9 100644 --- a/runtime/runtime_common.cc +++ b/runtime/runtime_common.cc @@ -371,30 +371,11 @@ static bool IsTimeoutSignal(int signal_number) { #pragma GCC diagnostic ignored "-Wframe-larger-than=" #endif -void HandleUnexpectedSignalCommon(int signal_number, - siginfo_t* info, - void* raw_context, - bool handle_timeout_signal, - bool dump_on_stderr) { - static bool handling_unexpected_signal = false; - if (handling_unexpected_signal) { - LogHelper::LogLineLowStack(__FILE__, - __LINE__, - ::android::base::FATAL_WITHOUT_ABORT, - "HandleUnexpectedSignal reentered\n"); - if (handle_timeout_signal) { - if (IsTimeoutSignal(signal_number)) { - // Ignore a recursive timeout. - return; - } - } - _exit(1); - } - handling_unexpected_signal = true; - - gAborting++; // set before taking any locks - MutexLock mu(Thread::Current(), *Locks::unexpected_signal_lock_); - +static void HandleUnexpectedSignalCommonDump(int signal_number, + siginfo_t* info, + void* raw_context, + bool handle_timeout_signal, + bool dump_on_stderr) { auto logger = [&](auto& stream) { bool has_address = (signal_number == SIGILL || signal_number == SIGBUS || signal_number == SIGFPE || signal_number == SIGSEGV); @@ -453,6 +434,71 @@ void HandleUnexpectedSignalCommon(int signal_number, } } +void HandleUnexpectedSignalCommon(int signal_number, + siginfo_t* info, + void* raw_context, + bool handle_timeout_signal, + bool dump_on_stderr) { + // Local _static_ storing the currently handled signal (or -1). + static int handling_unexpected_signal = -1; + + // Whether the dump code should be run under the unexpected-signal lock. For diagnostics we + // allow recursive unexpected-signals in certain cases - avoid a deadlock. + bool grab_lock = true; + + if (handling_unexpected_signal != -1) { + LogHelper::LogLineLowStack(__FILE__, + __LINE__, + ::android::base::FATAL_WITHOUT_ABORT, + "HandleUnexpectedSignal reentered\n"); + // Print the signal number. Don't use any standard functions, just some arithmetic. Just best + // effort, with a minimal buffer. + if (0 < signal_number && signal_number < 100) { + char buf[] = { ' ', + 'S', + static_cast<char>('0' + (signal_number / 10)), + static_cast<char>('0' + (signal_number % 10)), + '\n', + 0 }; + LogHelper::LogLineLowStack(__FILE__, + __LINE__, + ::android::base::FATAL_WITHOUT_ABORT, + buf); + } + if (handle_timeout_signal) { + if (IsTimeoutSignal(signal_number)) { + // Ignore a recursive timeout. + return; + } + } + // If we were handling a timeout signal, try to go on. Otherwise hard-exit. + // This relies on the expectation that we'll only ever get one timeout signal. + if (!handle_timeout_signal || handling_unexpected_signal != GetTimeoutSignal()) { + _exit(1); + } + grab_lock = false; // The "outer" handling instance already holds the lock. + } + handling_unexpected_signal = signal_number; + + gAborting++; // set before taking any locks + + if (grab_lock) { + MutexLock mu(Thread::Current(), *Locks::unexpected_signal_lock_); + + HandleUnexpectedSignalCommonDump(signal_number, + info, + raw_context, + handle_timeout_signal, + dump_on_stderr); + } else { + HandleUnexpectedSignalCommonDump(signal_number, + info, + raw_context, + handle_timeout_signal, + dump_on_stderr); + } +} + #if defined(__APPLE__) #pragma GCC diagnostic pop #endif |