Conversation
* use `std::nothrow` `new` consistently to keep exception-free semantics for allocation * rename static crashpad_handler to have no module-public prefix * use `nullptr` for arguments where we previously used 0 to clarify that those are pointers * eliminate the `memset()` of the `crashpad_state_t` initialization since it now contains non-trivially constructable fields (`std::atomic`) and replace it with `new` and an empty value initializer.
…ld, since libraries like libunwind.a might be packaged without PIC.
…ms with architecture prefixes (32-bit Linux)
…stack also ensure to get the first frame harmonize libunwind usage
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
…m is not enough, because the android tests run on macOS runners)
…sed unwinder to recover a frame when the callee has no frame record. So, lets limit that particular test-case to aarch64.
|
Summary of all technical changes since the last review (@mujacica, @JoshuaMoelans, @jpnurmi)
|
jpnurmi
left a comment
There was a problem hiding this comment.
Are the crashpad and breakpad changes related?
| * This is a replacement for `snprintf` in signal handlers: | ||
| * - signal-safe: uses no stdio, malloc, locks, or thread-local state. | ||
| * - reentrant: only stack locals; no writable globals. | ||
| * Returns 0 on success. |
There was a problem hiding this comment.
"Returns 0 on success" but returns bool
There was a problem hiding this comment.
True, I only copied the code from the old branch and didn't check whether the inline docs survived the code changes. Thanks. The function should likely not return anything.
Only in the sense that I was getting compiler errors with |
This is a more elaborate, long-term fix to getsentry/sentry-java#4830 than #1444.
It also finishes the work done here: #1088
And fixes the issues raised here:
sentry__enter_signal_handler#1353abort()#591So, while the driver for this PR is a downstream issue that exposes the signal-unsafety of some parts of the current
inprocimplementation, it also addresses a much broader range of concerns that regularly affectinprocusers on all platforms.At a high level, it introduces a separate handler thread for
inproc, which the signal handler (orUEFon Windows) wakes after it exchanges crash context data.The idea is that we minimize signal handler/UEF to do the least amount of syscall stuff (or at least the subset documented in the signal-safety man-page), while the handler thread can execute functions outside that range (with limitations, since thread sync and heap allocations are still problematic). This allows us to reuse
stdiofunctionality like formatters without running squarely into UB territory or having to rewrite all utilities to async-signal-safe versions, as in #1444.There are a few considerable changes to mention:
backtrace()or any unwinder that runs from the "current" instruction address is entirely useless (ignoring the fact thatbacktrace()was always signal-unsafe to begin with, which itself was the source of crashes, hangs or just empty stack traces).inproc, which we already partially acknowledged in Using libunwind for mac, since backtrace do not expect thread context… #1088 and fix: support musl on Linux #1233.libunwind(thenognuimplementation, not thellvmone, which is a pure C++ exception unwinder), which is a breaking change (at least in the sense that users now require an additional dependency at build and runtime). This means that the "general" Linux usage is now the same as with themusl libcenvironments.arm64andx86-64, and use the system-providedlibunwindfor the default stack-trace from a call-site. It turned out that the system-providedlibunwindwasn't safe enough to use in the context of the signal handler (either led to hangs or had issues with escaping the trampoline). This means users can now useinprocon macOS again (if their code is compiled without omitting frame pointers, which is always the case by default on macOS).Further improvements/fixes (summarizing the 30 commits, which I didn't want to squash):
libunwind-based unwinder modules now also validate retrieved ucontext pointers against memory mapping (for Linux and macOS)__syncfunctions and replaced them with__atomic(especially the signal handler blocking logic and the spinlock)newwithstd::nothrowthroughout the affected backend code (including the initialization ofcrashpad_state_t, which still usedmallocandmemsetalthough it hasstd::atomicmembers)TODOs:
x86-64stackwalker formacOS(and clean up the code)libbacktracefallback at all and how to handle it.inprocinprocnot working onmacOSlibunwinddependency on Linux