Skip to content

sentry_options_set_handler_strategy for native backend #1903

Description

@Thomas-Vos

My app is a Kotlin (JVM) app, which also loads a Kotlin/Native .so library for easy native interop. I use sentry-java, however, as that does not pick up native crashes I also need sentry-native in the Kotlin/Native module.

It seems that on Linux, the JVM sends some (non fatal) signal events, which it normally picks up and handles. But with sentry-native installed, the sentry-native signal handling picks it up instead, which gets reported and now crashes the app. I figured out for the inproc backend I can use this to fix the issue:

sentry_options_set_handler_strategy(options, SENTRY_HANDLER_STRATEGY_CHAIN_AT_START)

I would like to use the native backend, so could this feature please be supported for native, too?

Activity

  1. linear-code commented on Jul 23, 2026

    @linear-code
  2. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Jul 23, 2026
  3. jpnurmi commented on Jul 23, 2026

    @jpnurmi
    Collaborator

    @Thomas-Vos Unfortunately, there are no guarantees that SENTRY_HANDLER_STRATEGY_CHAIN_AT_START works sensibly with JVM, but it would be interesting to dig deeper into this.

    What kind of host platform is it? Desktop Linux? I wonder if it would be better to swap the signal handlers around by "pre-loading" sentry-native before the JVM runtime. It would probably give better results, because then JVM would be allowed to handle its own signals before sentry-native and thus, sentry-native doesn't need fragile heuristics for detecting non-fatal JVM-specific signals that have already been handled by JVM.

  4. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Jul 23, 2026
  5. Thomas-Vos commented on Jul 23, 2026

    @Thomas-Vos
    Author

    Yes, it is desktop Linux (and Windows). I'm using compose multiplatform, and for easy native interop I am using a Kotlin/Native libary. It is also built as a GraalVM app.

    I have been using sentry-native for quite some time already (inproc backend), but now I am updating it from 0.10.1 to 0.15.4 this is suddenly an issue. It worked fine before, so I guess something changed in sentry-native. It seems SENTRY_HANDLER_STRATEGY_CHAIN_AT_START resolves the issue, but I would have preferred to start using the native backend now.

    Your suggestion sounds great, but I don't know how to pre-load sentry-native before the JVM runtime. I currently initialize sentry-native in my Kotlin/Native .so library, which I load in Kotlin (JVM) code as early as possible in main function using System.load. But of course that is already after the JVM is running.

    I think for my use case, sentry_options_set_handler_strategy would be the easiest fix. What do you think?

  6. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Jul 23, 2026
  7. jpnurmi commented on Jul 23, 2026

    @jpnurmi
    Collaborator

    I have been using sentry-native for quite some time already (inproc backend), but now I am updating it from 0.10.1 to 0.15.4 this is suddenly an issue. It worked fine before, so I guess something changed in sentry-native.

    Just a wild guess, but one reason could be SA_NODEFER added in 0.13.0:

    Your suggestion sounds great, but I don't know how to pre-load sentry-native before the JVM runtime.

    I'm not sure either, and not familiar with how the entry point of such an application looks, but I'd perhaps try combining the techniques from #1613 and getsentry/sentry-cocoa#6193 if there's a place where you could inject a constructor function:

    extern void sentry__backend_preload(void);
    
    __attribute__((constructor)) static void
    onPreload(void)
    {
         sentry__backend_preload();
    }
  8. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Jul 23, 2026
  9. jpnurmi commented on Jul 23, 2026

    @jpnurmi
    Collaborator

    For reference, here's the CLR/Mono -specific assumption for SENTRY_HANDLER_STRATEGY_CHAIN_AT_START:

    // If the execution returns here in AOT mode, and the instruction
    // or stack pointer were changed, it means CLR/Mono converted the
    // signal into a managed exception and transferred execution to a
    // managed exception handler.
    // https://github.com/dotnet/runtime/blob/6d96e28597e7da0d790d495ba834cc4908e442cd/src/mono/mono/mini/exceptions-arm64.c#L538
    if (ip != get_instruction_pointer(uctx)
    || sp != get_stack_pointer(uctx)) {
    return;
    }

    If we'd call JVM's signal handler at the beginning of ours, there are no guarantees that execution returns, but in case JVM allows that, we'd need similar heuristics to detect whether the signal was handled or whether we need to continue crash handling.

  10. Thomas-Vos commented on Jul 23, 2026

    @Thomas-Vos
    Author

    Thanks, I am looking into it, signal handling seems more complicated that I thought.

    There is apparently a way to load native code before the JVM using LD_PRELOAD. And it seems signal chaining is supported this way.
    https://docs.oracle.com/en/java/javase/25/vm/signal-chaining.html. It would require me to make changes to my app distribution with some sort of wrapper script.

    However, I am using GraalVM instead, and cannot find the same docs there. In the past, signal handlers were not installed at all by GraalVM. But it seems that changed, and GraalVM now also installs signal handlers by default. It is not clear to me whether the LD_PRELOAD trick is supported in GraalVM.

    If we'd call JVM's signal handler at the beginning of ours, there are no guarantees that execution returns, but in case JVM allows that, we'd need similar heuristics to detect whether the signal was handled or whether we need to continue crash handling.

    If this is indeed the case, I find it surprising that it appears to work. When using sentry-native without SENTRY_HANDLER_STRATEGY_CHAIN_AT_START, my app immediately crashes due to a SIGSEGV (probably from the JVM). But as soon as I set SENTRY_HANDLER_STRATEGY_CHAIN_AT_START it works. The SIGSEGV does not appear. And when a fatal crash does appear in native code the event is still uploaded to sentry. I am not familiar with the details, but it seems the JVM also modifies ip/sp as it works as expected?

  11. moved this to Waiting for: Product Owner in GitHub Issues with 👀 3on Jul 23, 2026
  12. Thomas-Vos commented on Jul 23, 2026

    @Thomas-Vos
    Author

    After some more testing it seems that with GraalVM the SENTRY_HANDLER_STRATEGY_CHAIN_AT_START option is not even needed. It seems to work fine without it, despite GraalVM installing signal handlers. They are apparently not important. So GraalVM with sentry-native is no issue, and I just verified it works with the native backend, too.

    So this issue is only relevant to the JVM (for non-native builds) where either SENTRY_HANDLER_STRATEGY_CHAIN_AT_START is needed or sentry signal handlers need to be installed before the JVM. For my use case, I can just disable sentry-native on the JVM. I only use the JVM for fast builds for testing locally, and my users only get GraalVM builds.

    Still, it would be nice if SENTRY_HANDLER_STRATEGY_CHAIN_AT_START could be supported as it is an easy fix for the JVM. It definitely would all be easier if sentry-java could just report native crashes.

  13. moved this from Waiting for: Product Owner to No status in GitHub Issues with 👀 3on Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions