From efe96c8d149e35266e6df6c9c48ddbca19b41e62 Mon Sep 17 00:00:00 2001 From: Mischan Toosarani-Hausberger Date: Thu, 19 Feb 2026 00:46:19 +0100 Subject: [PATCH] fix(native): document inproc backend handler thread --- .../native/advanced-usage/backend-tradeoffs/index.mdx | 8 ++++++-- .../native/advanced-usage/signal-handling/index.mdx | 8 +++++--- .../advanced-usage/stack-overflow-handling/index.mdx | 7 +++++-- docs/platforms/native/configuration/backends/index.mdx | 5 ++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/platforms/native/advanced-usage/backend-tradeoffs/index.mdx b/docs/platforms/native/advanced-usage/backend-tradeoffs/index.mdx index ced2a9443bef8f..2486d3b2b5435d 100644 --- a/docs/platforms/native/advanced-usage/backend-tradeoffs/index.mdx +++ b/docs/platforms/native/advanced-usage/backend-tradeoffs/index.mdx @@ -50,7 +50,9 @@ Both backends are comparable in how they differ from `crashpad`. However, there * `inproc` only provides the backtrace of the crashing thread. `breakpad` records all threads in the minidump. * similar to `crashpad`, `breakpad` uses the lowest level error handling mechanism on each platform (macOS: mach exception ports, Windows: `UnhandledExceptionFilter`, Linux: signal handlers), it does cover a smaller range of errors, though, as mentioned above. * `inproc` uses signal handling on macOS, meaning you only get a `POSIX` compatibility layer over Mach exception ports. It relies on the same mechanisms as `breakpad` on Windows and Linux. -* as a result of choosing signal handling on macOS, `inproc` is currently broken on macOS since Apple eliminated unwinding from signal handlers +* on all platforms, `inproc` delegates crash processing from the signal handler (or `UnhandledExceptionFilter` on Windows) to a separate handler thread. The signal handler does minimal work (exchanging crash context and waking the handler thread) while the handler thread performs stack walking, event construction, and reporting. +* if the handler thread is unavailable (for example, because synchronization failed, the thread crashed, or never started), `inproc` falls back to processing directly in the signal handler. +* on macOS, the handler thread uses a frame-pointer-based stack walker for arm64 and x86-64, which avoids the limitations that previously made `inproc` unusable on recent macOS versions. * `inproc` is exceptionally lightweight and written entirely in C, meaning it does not rely on a weighty C++ runtime library, which is also more often affected by ABI incompatibilities * `breakpad` generates minidumps (like `crashpad` does), whereas `inproc` follows the Sentry event structure and primarily defers to the OS-provided unwinder and symbolication capabilities. Sentry processing infrastructure can extract more information from the provided minidump than from just a stack trace and registers. However, it also means that the crash context inside the minidump will remain opaque until it is processed in the backend. In contrast, if required, a local `relay` instance (or another application-level proxy) could process an entire `inproc` event with only JSON parsing capabilities. @@ -62,8 +64,10 @@ Both backends are comparable in how they differ from `crashpad`. However, there * want minimal dependencies * want the smallest footprint for the resulting artifact -* don't need to support the latest macOS versions * find the minimal feature set compared to `breakpad` and `crashpad` sufficient for your scenario +* want primarily client-side stack traces +* want to inspect the fully available event context in a hook +* look for a backend that runs on all supported platforms with an equivalent support for the user-facing API ### Summary diff --git a/docs/platforms/native/advanced-usage/signal-handling/index.mdx b/docs/platforms/native/advanced-usage/signal-handling/index.mdx index 3ab17a17285c4c..f22c56019dafb6 100644 --- a/docs/platforms/native/advanced-usage/signal-handling/index.mdx +++ b/docs/platforms/native/advanced-usage/signal-handling/index.mdx @@ -42,9 +42,11 @@ If you use the `crashpad` backend, in addition to the above, on Linux, you will ## What to Consider When Writing `on_crash` Hooks -The callback that you register as an `on_crash` hook runs in the context of a signal handler. (`before_send` also runs in the context of a signal handler, unless you turned it off for crashes.) +The callback that you register as an `on_crash` hook runs in the context of a crash handler. For the `inproc` backend on all platforms, the hook typically runs on a separate handler thread that is woken by the signal handler (or `UnhandledExceptionFilter` on Windows), rather than directly inside the signal handler itself. -Since signal handlers can interrupt the running process (and even each other) at any time, take special care when writing them. +If the handler thread is unavailable, `inproc` falls back to running the hook directly in the signal handler. For `crashpad` and `breakpad`, the hook runs in the context of their respective exception handling mechanisms. (`before_send` also runs in this context, unless you turned it off for crashes.) + +Although the `inproc` handler thread is not a signal handler, take special care when writing hooks because thread synchronization and heap allocations are still problematic in the context of a crashed process. Our developer documentation provides [guidelines for writing signal handlers](https://develop.sentry.dev/sdk/signal-handlers/). If you run on Linux or Android, these guidelines also apply to hooks. Signal handlers are notoriously difficult to work with, so it is crucial to follow these guidelines in order to avoid causing severe faults (like crashes and deadlocks), which can prevent terminating programs and sending reports. @@ -58,4 +60,4 @@ Further, it is crucial to understand that this signal handler stack configuratio This differs from the situation on Android, where the `Bionic libc` `pthread` implementation initializes each thread with a separate signal handler stack. `Bionic` sets the Android stack sizes from above, and the Android Runtime Team recommends _not_ overwriting these settings. -In this scenario, most of the above-defined stack sizes will be fully available to your defined `on_crash` hook. Still, be considerate of stack usage. If you need to fill any large data structures within the hook, we recommend pre-allocating them at initialization and only filling the values within the hook. +In this scenario, most of the above-defined stack sizes will be fully available to your defined `on_crash` hook. Still, be considerate of stack usage. If you need to fill any large data structures within the hook, we recommend pre-allocating them at initialization and only filling the values within the hook. diff --git a/docs/platforms/native/advanced-usage/stack-overflow-handling/index.mdx b/docs/platforms/native/advanced-usage/stack-overflow-handling/index.mdx index 1a60f5cddc7eb6..45d72c0c08162c 100644 --- a/docs/platforms/native/advanced-usage/stack-overflow-handling/index.mdx +++ b/docs/platforms/native/advanced-usage/stack-overflow-handling/index.mdx @@ -125,6 +125,9 @@ or care than other crashes. Be aware that, in contrast to Mach exception port usage, signal handlers on macOS run on the same thread that caused the -signal and thus also need a `sigaltstack` to handle any crash from a stack overflow. Only the `inproc` backend on macOS -currently relies entirely on signal handlers, and its signal stack is set up equivalently to Linux or other POSIX platforms. +signal and thus also need a `sigaltstack` to handle any crash from a stack overflow. The `inproc` backend relies on signal +handlers on macOS and Linux but, on all platforms, delegates crash processing to a separate handler thread. + +Both the thread on which the SDK was initialized and the handler thread receive a `sigaltstack` if one is not already +configured, which helps prevent stack overflow from interfering with crash reporting. diff --git a/docs/platforms/native/configuration/backends/index.mdx b/docs/platforms/native/configuration/backends/index.mdx index 21f6f56a62f931..c51a535afe1e0e 100644 --- a/docs/platforms/native/configuration/backends/index.mdx +++ b/docs/platforms/native/configuration/backends/index.mdx @@ -15,8 +15,7 @@ CMake option, with support for the following options: - [`crashpad`](crashpad/): This uses the out-of-process crashpad handler. It is used as the default on Windows, macOS, and Linux. - `breakpad`: This uses the in-process breakpad handler. -- `inproc`: A small in-process handler supported on all platforms -and used as a default on Android. It has no longer worked on macOS since version 13 ("Ventura"). +- `inproc`: A small in-process handler supported on all platforms and used as a default on Android. - `none`: This builds `sentry-native` without a backend, so it does not handle crashes. It is primarily used for tests. @@ -26,5 +25,5 @@ send a crash to Sentry immediately after it happens. Instead, the crash report i written to disk and sent the next time the application is run. Since `Crashpad` runs in a different process, it doesn't have this limitation. -The [Advanced Usage](/platforms/native/advanced-usage/backend-tradeoffs) section +The [Advanced Usage](/platforms/native/advanced-usage/backend-tradeoffs) section explains the trade-offs in choosing the correct backend for your use case.