mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:39:49 +00:00
Dump stack trace on segfault in the VM.
Install a signal handler in the standalone VM that dumps a backtrace similar to what we already do on assertion failures. For now only Linux and MacOS are supported. BUG= R=asiva@google.com Review URL: https://codereview.chromium.org/2514113002 .
This commit is contained in:
parent
7d287b232b
commit
6cd141def5
|
@ -22,6 +22,12 @@ char* Platform::resolved_executable_name_ = NULL;
|
|||
int Platform::script_index_ = 1;
|
||||
char** Platform::argv_ = NULL;
|
||||
|
||||
|
||||
static void segv_handler(int signal, siginfo_t* siginfo, void* context) {
|
||||
Dart_DumpNativeStackTrace(context);
|
||||
abort();
|
||||
}
|
||||
|
||||
bool Platform::Initialize() {
|
||||
// Turn off the signal handler for SIGPIPE as it causes the process
|
||||
// to terminate on writing to a closed pipe. Without the signal
|
||||
|
@ -33,6 +39,21 @@ bool Platform::Initialize() {
|
|||
perror("Setting signal handler failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
act.sa_sigaction = &segv_handler;
|
||||
if (sigemptyset(&act.sa_mask) != 0) {
|
||||
perror("sigemptyset() failed.");
|
||||
return false;
|
||||
}
|
||||
if (sigaddset(&act.sa_mask, SIGPROF) != 0) {
|
||||
perror("sigaddset() failed");
|
||||
return false;
|
||||
}
|
||||
if (sigaction(SIGSEGV, &act, NULL) != 0) {
|
||||
perror("sigaction() failed.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,20 @@ bool Platform::Initialize() {
|
|||
perror("Setting signal handler failed");
|
||||
return false;
|
||||
}
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
act.sa_sigaction = &segv_handler;
|
||||
if (sigemptyset(&act.sa_mask) != 0) {
|
||||
perror("sigemptyset() failed.");
|
||||
return false;
|
||||
}
|
||||
if (sigaddset(&act.sa_mask, SIGPROF) != 0) {
|
||||
perror("sigaddset() failed");
|
||||
return false;
|
||||
}
|
||||
if (sigaction(SIGSEGV, &act, NULL) != 0) {
|
||||
perror("sigaction() failed.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -3281,4 +3281,10 @@ Dart_CreateAppJITSnapshot(uint8_t** vm_isolate_snapshot_buffer,
|
|||
*/
|
||||
DART_EXPORT bool Dart_IsPrecompiledRuntime();
|
||||
|
||||
|
||||
/**
|
||||
* Print a native stack trace. Used for crash handling.
|
||||
*/
|
||||
DART_EXPORT void Dart_DumpNativeStackTrace(void* context);
|
||||
|
||||
#endif /* INCLUDE_DART_API_H_ */ /* NOLINT */
|
||||
|
|
|
@ -6671,4 +6671,9 @@ DART_EXPORT bool Dart_IsPrecompiledRuntime() {
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
DART_EXPORT void Dart_DumpNativeStackTrace(void* context) {
|
||||
Profiler::DumpStackTrace(context);
|
||||
}
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -944,7 +944,36 @@ static uintptr_t __attribute__((noinline)) GetProgramCounter() {
|
|||
#endif
|
||||
|
||||
|
||||
void Profiler::DumpStackTrace(void* context) {
|
||||
#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_MACOS)
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||
mcontext_t mcontext = ucontext->uc_mcontext;
|
||||
uword pc = SignalHandler::GetProgramCounter(mcontext);
|
||||
uword fp = SignalHandler::GetFramePointer(mcontext);
|
||||
uword sp = SignalHandler::GetCStackPointer(mcontext);
|
||||
DumpStackTrace(/* native_stack_trace = */ true, sp, fp, pc);
|
||||
#else
|
||||
// TODO(fschneider): Add support for more platforms.
|
||||
// Do nothing on unsupported platforms.
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Profiler::DumpStackTrace(bool native_stack_trace) {
|
||||
uintptr_t sp = Thread::GetCurrentStackPointer();
|
||||
uintptr_t fp = 0;
|
||||
uintptr_t pc = GetProgramCounter();
|
||||
|
||||
COPY_FP_REGISTER(fp);
|
||||
|
||||
DumpStackTrace(native_stack_trace, sp, fp, pc);
|
||||
}
|
||||
|
||||
|
||||
void Profiler::DumpStackTrace(bool native_stack_trace,
|
||||
uword sp,
|
||||
uword fp,
|
||||
uword pc) {
|
||||
// Allow only one stack trace to prevent recursively printing stack traces if
|
||||
// we hit an assert while printing the stack.
|
||||
static uintptr_t started_dump = 0;
|
||||
|
@ -970,12 +999,6 @@ void Profiler::DumpStackTrace(bool native_stack_trace) {
|
|||
native_stack_trace ? "native" : "dart-only",
|
||||
OSThread::ThreadIdToIntPtr(os_thread->trace_id()));
|
||||
|
||||
uintptr_t sp = Thread::GetCurrentStackPointer();
|
||||
uintptr_t fp = 0;
|
||||
uintptr_t pc = GetProgramCounter();
|
||||
|
||||
COPY_FP_REGISTER(fp);
|
||||
|
||||
uword stack_lower = 0;
|
||||
uword stack_upper = 0;
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ class Profiler : public AllStatic {
|
|||
|
||||
static SampleBuffer* sample_buffer() { return sample_buffer_; }
|
||||
|
||||
static void DumpStackTrace(void* context);
|
||||
static void DumpStackTrace(bool native_stack_trace = true);
|
||||
|
||||
static void SampleAllocation(Thread* thread, intptr_t cid);
|
||||
|
@ -74,6 +75,11 @@ class Profiler : public AllStatic {
|
|||
}
|
||||
|
||||
private:
|
||||
static void DumpStackTrace(bool native_stack_trace,
|
||||
uword sp,
|
||||
uword fp,
|
||||
uword pc);
|
||||
|
||||
// Does not walk the thread's stack.
|
||||
static void SampleThreadSingleFrame(Thread* thread, uintptr_t pc);
|
||||
static bool initialized_;
|
||||
|
|
Loading…
Reference in a new issue