SIGABRT signals don't create core dumps

David Holmes david.holmes at oracle.com
Tue Feb 17 02:16:25 UTC 2026


On 17/02/2026 10:30 am, Álvaro Torres Cogollo wrote:
>  >why is the call to abort() not triggering a coredump?
> 
> I guess you mean that the JVM generates coredumps by calling abort() as 
> I read in:
> https://github.com/openjdk/jdk/blob/jdk-25%2B36/src/hotspot/os/posix/ 
> os_posix.cpp#L2091
> 
> But glibc calls abort() and apparently doesn't generate the coredump.
> 
> This is beyond my knowledge of the topic. The only thing I can try to 
> help with is that I did a quick test you can see at:
> https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug/ 
> commit/891969416579c7d6a8df6f3b10007a7c78f8ae61
> 
> The relevant code:
> 
>     // src/main/kotlin/com/example/demo/controller/CrashController.kt
>     ...
>     @RequestMapping("/crash")
>     class CrashController {
>          @GetMapping("/abort")
>          fun crashWithAbort(): String {
>              return NativeCrasher.crashWithAbort()
>          }
>     ...
> 
> 
>     // src/main/kotlin/com/example/demo/native/NativeCrasher.kt
>     ...
>     object NativeCrasher {
>          init {
>              LibraryLoader.load()h
>          }
>          external fun crashWithAbort(): String
>     ...
> 
> 
>     // src/main/c/native_crasher.c
>     ...
>     JNIEXPORT void JNICALL Java_com_example_demo_native_NativeCrasher_crashWithAbort
>        (JNIEnv *env, jobject obj)
>     {
>          abort();
>     }
>     ...
> 
> If I hit the endpoint with JDK25:
> 
>     curl localhost:8080/crash/abort
> 
> I don't get any coredump from that but only this exit code:
> 
>     exited with code 133

That indicates the process terminated via SIGTRAP not SIGABRT.
> The PoC repository uses docker and everything is pretty standard apart 

I have a suspicion that it is the Docker environment that is causing the 
problem.

David
-----

> from the optional patched compilation of the JVM to register the SIGABRT 
> handler:
> https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug/ 
> blob/891969416579c7d6a8df6f3b10007a7c78f8ae61/Dockerfile
> 
>     FROM amazoncorretto:25 AS amazoncorretto-25
>     #FROM amazoncorretto-25-patched AS amazoncorretto-25 # Use this instead to use the patched JVM
> 
>     FROM amazoncorretto-25
> 
>     WORKDIR /app
> 
>     # Copy built JAR from builder
>     COPY --from=builder /build/build/libs/*.jar app.jar
> 
>     # Expose port
>     EXPOSE 8080
> 
>     # Run application
>     ENTRYPOINT ["java", "-jar", "app.jar"]
> 
> 
> Álvaro
> 
> 
> On 16/2/26 22:33, David Holmes wrote:
>> On 16/02/2026 9:27 pm, Álvaro Torres Cogollo wrote:
>>> I believe what happens is that something has a bug and does an 
>>> invalid call to free() that makes glibc to call abort(). And since 
>>> there is no handler for that, nothing generates a core dump and it 
>>> just ends.
>>>
>>> Based on this stackoverflow post:
>>> https://stackoverflow.com/a/151568
>>>
>>>      As for how to debug it, installing a handler for SIGABRT is 
>>> probably the best way to proceed. You can set a breakpoint in your 
>>> handler or deliberately trigger a core dump.
>>
>> I think you are missing my point. I get that glibc calls abort() but 
>> that in itself should trigger a coredump. You don't have to install a 
>> handler for SIGABRT for abort() to create a coredump.
>>
>> So my question remains: why is the call to abort() not triggering a 
>> coredump?
>>
>> I wonder if glibc doesn't actually call abort() but just raises 
>> SIGABRT directly? And if so why? It sounds like you can control what 
>> glibc does for these kinds of errors so perhaps you need to be telling 
>> glibc to do something different?
>>
>> David
>> ------
>>> Álvaro
>>>
>>>
>>> On 16/2/26 11:41, David Holmes wrote:
>>>> On 13/02/2026 7:25 pm, Álvaro Torres Cogollo wrote:
>>>>> Hi,
>>>>>
>>>>> In my opinion, I think it's fair to assume that other libraries 
>>>>> shouldn't call abort() if they actively don't want it to generate a 
>>>>> core dump. At least in the context of a Spring Boot server, I can't 
>>>>> think of a valid reason to call abort from a library and don't 
>>>>> expect a core dump.
>>>>
>>>> My query is: how is it calling abort but not getting a coredump?
>>>>
>>>> David
>>>>> However, I understand the concern about handling SIGABRT signals in 
>>>>> hosting environments. I'm also missing a huge context on the 
>>>>> implications of this. Maybe it's enough to create a flag like -XX: 
>>>>> +CreateCoreDumpOnAbort, -XX:+HandleAbort or -XX:+CrashOnAbort. That 
>>>>> could be a best-practice configuration so far in certain contexts 
>>>>> (Spring Boot) and eventually consider making this the default 
>>>>> behaviour.
>>>>>
>>>>> Regards,
>>>>>
>>>>> Álvaro
>>>>>
>>>>>
>>>>> On 13/2/26 08:07, David Holmes wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On 13/02/2026 3:16 am, Álvaro Torres Cogollo wrote:
>>>>>>> Hi again,
>>>>>>>
>>>>>>> I just realized that I made a typo in the reproduction repository 
>>>>>>> link. This is the right one:
>>>>>>>
>>>>>>> https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug
>>>>>>>
>>>>>>> Sorry about that.
>>>>>>>
>>>>>>> Álvaro
>>>>>>>
>>>>>>>
>>>>>>> On 12/2/26 18:04, Álvaro Torres Cogollo wrote:
>>>>>>>> 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.
>>>>>>
>>>>>> This is the right place (hotspot-runtime-dev would also have done 
>>>>>> but a narrower audience).
>>>>>>
>>>>>> Not sure it is a bug as such. I'm missing a piece of the puzzle 
>>>>>> here. These other libraries are presumably calling abort() to 
>>>>>> raise the SIGABRT but there is no coredump. Yet if the VM calls 
>>>>>> abort() there is a coredump. I'm not seeing why there would be 
>>>>>> different behaviour.
>>>>>>
>>>>>> Catching SIGABRT in the VM then re-calling abort() may fix your 
>>>>>> issue, but I'm not sure if it could introduce problems for hosting 
>>>>>> environments which may already catch SIGABRT themselves.
>>>>>>
>>>>>> Need to hear what other think about this.
>>>>>>
>>>>>> Cheers,
>>>>>> David
>>>>>> -----
>>>>>>
>>>>>>>> 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
>>>>>>>>
>>>>>>
>>>>
>> ---
>>



More information about the hotspot-dev mailing list