Skip to content

Native crash (SIGSEGV) on process shutdown #212

Open

Description

@KF-Miyata

Describe the bug
Runtime behavior is fine during execution, but a native crash occurs on program exit.

# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f310ed1610d, pid=252732, tid=0x00007f3140569700
#
# JRE version: OpenJDK Runtime Environment (8.0_432-b06) (build 1.8.0_432-432-b06)
# Java VM: OpenJDK 64-Bit Server VM (25.432-b06 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C  [libwebrtc-java-linux-x86_642121276466645068163.so+0x4d010d]  jni::JavaFactory<webrtc::RtpTransceiverInterface>::~JavaFactory()+0x2d
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dev/hs_err_pid252732.log

To Reproduce
Minimal code:

import dev.onvoid.webrtc.media.audio.AudioProcessing;

public class Repro {
    public static void main(String[] args) {
        AudioProcessing ap = new AudioProcessing();
        ap.dispose();
    }
}

Gradle dependencies:

implementation "dev.onvoid.webrtc:webrtc-java:0.14.0"
implementation group: "dev.onvoid.webrtc", name: "webrtc-java", version: "0.14.0", classifier: "linux-x86_64"

Expected behavior
Process should exit cleanly with no crash

Desktop (please complete the following information):

  • OS: AlmaLinux 8.10 (Cerulean Leopard)
  • Architecture: x86_64

Activity

  1. devopvoid commented on Sep 19, 2025

    @devopvoid
    Owner

    Thanks for the report! I see that you are using the OpenJDK Runtime Environment (8.0_432-b06), which is quite outdated.

    Unfortunately, I can't reproduce the issue on AlmaLinux 8 using newer JDKs. I will try it with JDK 8 later.

    Could you also try to reproduce this behaviour with JDK 17, for example?

  2. KF-Miyata commented on Sep 24, 2025

    @KF-Miyata
    Author

    Thank you for your reply, and I apologize for the delay.
    I have tested with JDK 17, and I can confirm that the issue does not occur with that version.

  3. kalgecin commented on Sep 25, 2025

    @kalgecin
    Contributor

    I'm also seeing SIGSEGV on JVM 25

    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    #  SIGSEGV (0xb) at pc=0x00007fd4b21817e7, pid=178907, tid=179957
    #
    # JRE version: OpenJDK Runtime Environment Corretto-25.0.0.36.2 (25.0+36) (build 25+36-LTS)
    # Java VM: OpenJDK 64-Bit Server VM Corretto-25.0.0.36.2 (25+36-LTS, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, linux-amd64)
    # Problematic frame:
    # C  [libwebrtc-java-linux-x86_649756144665632658865.so+0x84a7e7]
    #
    # Core dump will be written. Default location: Core dumps may be processed with "/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %h %d %F" (or dumping to /home/kalgecin/***/core.178907)
    #
    # If you would like to submit a bug report, please visit:
    #   https://github.com/corretto/corretto-25/issues/
    # The crash happened outside the Java Virtual Machine in native code.
    # See problematic frame for where to report the bug.
    #
    
    ---------------  S U M M A R Y ------------
    
    Command Line: -Dvisualvm.id=12399302740675 -Xmx20G -XX:TieredStopAtLevel=1 -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -javaagent:/home/kalgecin/.local/share/JetBrains/Toolbox/apps/intellij-idea-ultimate/lib/idea_rt.jar=44989 -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 com.****
    
    Host: AMD Ryzen 5 3600 6-Core Processor, 12 cores, 62G, Manjaro Linux
    Time: Thu Sep 25 09:43:23 2025 UTC elapsed time: 140.269789 seconds (0d 0h 2m 20s)
    
    ---------------  T H R E A D  ---------------
    
    Current thread (0x00007fd3b0025e10):  JavaThread "Thread-10"        [_thread_in_native, id=179957, stack(0x00007fd440eeb000,0x00007fd4416eb000) (8192K)]
    
    Stack: [0x00007fd440eeb000,0x00007fd4416eb000],  sp=0x00007fd4416e9d90,  free space=8187k
    Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
    C  [libwebrtc-java-linux-x86_649756144665632658865.so+0x84a7e7]
    C  [libwebrtc-java-linux-x86_649756144665632658865.so+0x849ba6]
    C  [libwebrtc-java-linux-x86_649756144665632658865.so+0x84b1f9]
    C  [libc.so.6+0x969cb]
    
    siginfo: si_signo: 11 (SIGSEGV), si_code: 2 (SEGV_ACCERR), si_addr: 0x00007fd41d2d88c8
    
  4. kalgecin commented on Sep 26, 2025

    @kalgecin
    Contributor

    but mine comes from peerConnectionFactory.dispose(). I will try to reproduce with minimal code and probably open a new ticket

  5. kalgecin commented on Sep 26, 2025

    @kalgecin
    Contributor

    Figured out my problem. I was trying to dispose peer connection factory from within PeerConnectionObserver (that was passed into factory.createPeerConnection). Changing the logic around fixed the problem.

  6. selfancy commented on Nov 1, 2025

    @selfancy

    Can it be compatible with Java 8?

  7. devopvoid commented on Sep 13, 2026

    @devopvoid
    Owner

    Thanks for the detailed report and reproduction, and thanks @KF-Miyata for confirming this doesn't occur on JDK 17.

    I looked into the crash trace more closely. It's happening in jni::JavaFactory<webrtc::RtpTransceiverInterface>::~JavaFactory() — but that class is never exercised by the repro (new AudioProcessing(); dispose();). That destructor only runs when the process-wide static factory map (JavaFactories::getFactoryMap()) is torn down at process exit, destroying every registered JavaFactory<T> in some order — it just happened to be RtpTransceiverInterface's turn when the crash was captured, it's not specific to that type.

    ~JavaFactory() itself is written defensively — it only calls javaClass.release(), which just nulls the held global ref without touching JNI, specifically so the subsequent JavaGlobalRef destructor becomes a no-op and never calls DeleteGlobalRef during static teardown. So the crash is likely one level deeper: something about the C++ static/global destruction order at process exit vs. the JVM's own shutdown/native-library-unload sequence on JDK 8 specifically (heap/allocator or std::any internals already torn down by the time this runs).

    I checked the two most relevant native fixes merged recently (#283 — JNI reference-counting/lifetime bugs, #269 — JNI thread attach/detach on JVM shutdown) and neither touches JavaFactory/JavaFactories or this static-teardown path, so this isn't fixed by anything that's landed so far. (@kalgecin's crash further down this thread turned out to be a separate, self-inflicted issue — disposing the factory reentrantly from inside its own PeerConnectionObserver callback — so that one isn't additional evidence here.)

    Since this seems specific to how JDK 8 tears down native libraries at process exit, and reproduction is difficult on newer JDKs, I likely need a JDK 8 environment myself to chase the actual static-destruction ordering. In the meantime — is System.exit() being called explicitly, or is this a plain fall-off-the-end-of-main shutdown? And does forcing a System.exit(0) right after dispose() change anything? That would help narrow down whether this is JVM-triggered shutdown-hook ordering vs. plain C++ atexit ordering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions