Repository navigation
No frames found when unwinding backtrace on Linux after SIGSEGV #384
Copy link
Copy link
Closed
Description
Description
Hello! I seem to be having an issue when Sentry tries to get stack frames after a segmentation fault on Linux where it ends up finding 0 frames. I debugged libsentry.so and found that sentry-native always skips getting the backtrace from libbacktrace because we always have a valid sentry_ucontext_t at the following trace:
(gdb) bt
#0 sentry__unwind_stack_libbacktrace (addr=0x0, uctx=0x55555559e310, ptrs=0x55555559de60, max_frames=128) at /home/mischa/dev/mutate/conan-sentry-native/source_subfolder/src/unwinder/sentry_unwinder_libbacktrace.c:9
#1 0x00007ffff7c90cfd in unwind_stack (addr=0x0, uctx=0x55555559e310, ptrs=0x55555559de60, max_frames=128) at /home/mischa/dev/mutate/conan-sentry-native/source_subfolder/src/unwinder/sentry_unwinder.c:27
#2 0x00007ffff7c90d64 in sentry_unwind_stack_from_ucontext (uctx=0x55555559e310, stacktrace_out=0x55555559de60, max_len=128) at /home/mischa/dev/mutate/conan-sentry-native/source_subfolder/src/unwinder/sentry_unwinder.c:45
#3 0x00007ffff7c94b07 in make_signal_event (sig_slot=0x7ffff7f86a98 <SIGNAL_DEFINITIONS+120>, uctx=0x55555559e310) at /home/mischa/dev/mutate/conan-sentry-native/source_subfolder/src/backends/sentry_backend_inproc.c:209
#4 0x00007ffff7c9471d in handle_ucontext (uctx=0x55555559e310) at /home/mischa/dev/mutate/conan-sentry-native/source_subfolder/src/backends/sentry_backend_inproc.c:263
#5 0x00007ffff7c9465f in handle_signal (signum=11, info=0x55555559e470, user_context=0x55555559e340) at /home/mischa/dev/mutate/conan-sentry-native/source_subfolder/src/backends/sentry_backend_inproc.c:308
#6 <signal handler called>
Because of the following code at https://github.com/getsentry/sentry-native/blob/master/src/unwinder/sentry_unwinder_libbacktrace.c#L15:
else if (uctx) {
return 0;
} else {
return backtrace(ptrs, max_frames);
}Changing that return 0 to return backtrace(ptrs, max_frames) works as expected, but I guess there's more going on here that I don't know about.
When does the problem happen
- During build
- During run-time
- When capturing a hard crash
Environment
- OS: Archlinux x86-64
- Compiler: Clang 10
- CMake version and config: 3.18.3, SENTRY_BACKEND=inproc
Steps To Reproduce
#include <iostream>
#include <sentry.h>
#include <thread>
#include <chrono>
int main(int argc, char** argv)
{
sentry_user_consent_give();
sentry_options_t *options = sentry_options_new();
sentry_options_set_dsn(options, !!!!);
sentry_options_set_environment(options, "development");
sentry_options_set_debug(options, 1);
if (sentry_init(options)) {
std::cerr << "Failed to initialize Sentry, crashes will not be reported!" << std::endl;
}
std::this_thread::sleep_for(std::chrono::seconds(3));
*(reinterpret_cast<int*>(0) + 1) = 0;
sentry_shutdown();
return 0;
}This reproduces it 100% of the time for me.
Log output
[sentry] INFO entering signal handler
[sentry] DEBUG captured backtrace with 0 frames
[sentry] DEBUG merging scope into event
[sentry] DEBUG trying to read modules from /proc/self/maps
[sentry] DEBUG inspecting module "/tmp/repro"
[sentry] DEBUG inspecting module "/usr/lib/libresolv-2.32.so"
[sentry] DEBUG inspecting module "/usr/lib/libnss_dns-2.32.so"
[sentry] DEBUG inspecting module "/usr/lib/libnss_resolve.so.2"
[sentry] DEBUG inspecting module "/usr/lib/libnss_myhostname.so.2"
[sentry] DEBUG inspecting module "/usr/lib/libnss_mymachines.so.2"
[sentry] DEBUG inspecting module "/usr/lib/libnss_files-2.32.so"
[sentry] DEBUG inspecting module "/usr/lib/liblzma.so.5.2.5"
[sentry] DEBUG inspecting module "/usr/lib/libdl-2.32.so"
[sentry] DEBUG inspecting module "/usr/lib/libpthread-2.32.so"
[sentry] DEBUG inspecting module "/usr/lib/librt-2.32.so"
[sentry] DEBUG inspecting module "/usr/lib/libc-2.32.so"
[sentry] DEBUG inspecting module "/usr/lib/libgcc_s.so.1"
[sentry] DEBUG inspecting module "/usr/lib/libm-2.32.so"
[sentry] DEBUG inspecting module "/usr/lib/libstdc++.so.6.0.28"
[sentry] DEBUG inspecting module "/usr/lib/libunwind.so.8.0.1"
[sentry] DEBUG inspecting module "/tmp/libsentry.so"
[sentry] DEBUG inspecting module "/usr/lib/ld-2.32.so"
[sentry] DEBUG inspecting module "linux-gate.so"
[sentry] DEBUG read 19 modules from /proc/self/maps
[sentry] DEBUG adding attachments to envelope
[sentry] DEBUG sending envelope
[sentry] DEBUG serializing envelope into buffer
[sentry] INFO crash has been captured
[1] 21361 segmentation fault (core dumped) LD_LIBRARY_PATH=. ./repro
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
Swatinem commentedon Sep 30, 2020
Its unfortunate that libbacktrace does not really give us the API to unwind from an arbitrary instruction pointer.
And having just sentry itself and
#6 <signal handler called>in the resolved stacktrace is kind of useless :-(We should at least document this restriction a bit better. We do support both crashpad and breakpad on linux, so those should be used in favor of the inproc backend.
GenuineAster commentedon Sep 30, 2020
I truncated the stack to contain what is relevant to solving the issue. That stack is from GDB. We do not invoke libbacktrace at all in sentry, that's the bug I'm trying to report.
The way we set up the signal handler in sentry-native means we will always get a
ucontextwhensigactionis invoked, and for some reason if we have a validucontext, sentry-native doesn't try to get a backtrace. If the accepted fix is to replace the aforementionedreturn 0with an attempt to invoke libbacktrace, then I can make a PR for that.Swatinem commentedon Oct 1, 2020
The problem here is that at least
execinfo.hdoes not provide functionality to unwind from an arbitrary ucontext. We would probably have to import/use a different library for that case.GenuineAster commentedon Oct 1, 2020
Yeah, but the callstack is reported properly if I just call
return backtrace(ptrs, max_frames)instead of just returning 0. Sure, I get a few frames in sentry-native, but we've configured filters in Sentry for our app-relevant frames and it displays nicely. We are using a fork of sentry-native with this fix (and a few others) and it is working as expected. I don't really see the need of just not unwinding at all.