SIGABRT signals don't create core dumps

Álvaro Torres Cogollo atorrescogollo at gmail.com
Thu Feb 12 17:04:13 UTC 2026


Hi,

We've been hitting a problem in production that I think might be a bug 
in hotspot's signal handling. Let me know if this should go somewhere else.

The issue is that when a native library crashes due to memory corruption 
(like an invalid free() call), the JVM exits immediately without 
generating any core dump or error report, even though we have 
-XX:+CreateCoredumpOnCrash enabled.

Here's what we're seeing when it crashes:

     munmap_chunk(): invalid pointer


Or when using tcmalloc:

     src/tcmalloc.cc:333] Attempt to free invalid pointer 0xffff38000b60


We're running with:

     JAVA_TOOL_OPTIONS=-XX:+CreateCoredumpOnCrash -XX:ErrorFile=/core-dumps/hs_err_pid%p.log


But when these crashes happen, we get nothing - just the error message 
above and the process dies. This makes debugging really difficult, 
especially since the crashes happen randomly in production.

After digging through the hotspot source, I noticed that signal handlers 
are installed for SIGSEGV, SIGBUS, SIGFPE, etc., but not for SIGABRT:

https://github.com/openjdk/jdk/blob/37dc1be67d4c15a040dc99dbc105c3269c65063d/src/hotspot/os/posix/signals_posix.cpp#L1352-L1358

When glibc detects the memory corruption, it calls abort() which raises 
SIGABRT. Since there's no handler for it, the JVM can't catch it and 
generate the diagnostics.

To demonstrate the issue, I put together a small reproduction case:

https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-handling

The repo has a Spring Boot app with three endpoints that show the problem:

1. /crash/unsafe - Uses Java Unsafe to write to address 0
    Result: SIGSEGV -> Works correctly, generates hs_err file

2. /crash/null - JNI code that dereferences a null pointer
    Result: SIGSEGV -> Works correctly, generates hs_err file

3. /crash/free - JNI code that calls free() on a stack variable
    Result: SIGABRT -> BROKEN, just prints "munmap_chunk(): invalid 
pointer" and dies

You can reproduce it with:

     docker-compose up -d
     curl localhost:8080/crash/free
     docker-compose logs


And you'll see it just prints the error and exits, no hs_err file gets 
created.

I also tested a potential fix by adding SIGABRT handling to hotspot. 
With that change, scenario 3 correctly generates an hs_err file and core 
dump. The patch basically:

https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug/blob/main/jdk17.patch

- Adds set_signal_handler(SIGABRT) in signals_posix.cpp
- Resets SIGABRT to SIG_DFL before calling abort() in os_posix.cpp to 
avoid recursive handling

After applying it, the /crash/free endpoint generates proper diagnostics:

     # SIGABRT (0x6) at pc=0x0000ffffbd177608 (sent by kill), pid=1, tid=41
     # Problematic frame:
     # C  [libc.so.6+0x87608]
     # Core dump will be written. Default location: //core
     # An error report file with more information is saved as:
     # /core-dumps/java_error1.log


I'm not sure if there's a specific reason why SIGABRT isn't handled 
currently. If there is, are there any alternative approaches to capture 
diagnostics when native libraries trigger abort()? For us and probably 
others dealing with native library bugs in production, having some way 
to get these diagnostics would be really valuable.

Thanks,

Álvaro
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/hotspot-dev/attachments/20260212/841142a6/attachment-0001.htm>


More information about the hotspot-dev mailing list