<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>I've been doing some tests. Using init has indeed effect on the
exit code:</p>
<blockquote>
<pre>services:
crash-test:
build: .
<b>init: true</b>
environment:
- JAVA_TOOL_OPTIONS=-XX:+CreateCoredumpOnCrash -XX:ErrorFile=/core-dumps/hs_err_pid%p.log
ports:
- "8080:8080"
volumes:
- ./core-dumps:/core-dumps</pre>
</blockquote>
<p>When using init=true makes it end with exit code 134 (SIGABRT).
With init=false , it ends with exit code 133 (SIGTRAP).</p>
<p>However, I still don't get any core dump in any of those cases.</p>
<p>Additionally, I think the equivalent for Kubernetes would be
setting shareProcessNamespace=true in the podSpec. That would
force me introduce a potential security risk just to get core
dumps. In some context you simply can't due to security policies.
So even if that would be the case, it would be very annoying if
the only way was using init/shareProcessNamespace.</p>
<p>Álvaro</p>
<p><br>
</p>
<div class="moz-cite-prefix">On 17/2/26 03:21, David Holmes wrote:<br>
</div>
<blockquote type="cite"
cite="mid:e7074ee2-e242-4f48-9e84-c1e720e5a447@oracle.com">Perhaps
you are running into this docker issue:
<br>
<br>
<a class="moz-txt-link-freetext" href="https://ddanilov.me/how-signals-are-handled-in-a-docker-container">https://ddanilov.me/how-signals-are-handled-in-a-docker-container</a>
<br>
<br>
David
<br>
-----
<br>
<br>
On 17/02/2026 12:16 pm, David Holmes wrote:
<br>
<blockquote type="cite">On 17/02/2026 10:30 am, Álvaro Torres
Cogollo wrote:
<br>
<blockquote type="cite"> >why is the call to abort() not
triggering a coredump?
<br>
<br>
I guess you mean that the JVM generates coredumps by calling
abort() as I read in:
<br>
<a class="moz-txt-link-freetext" href="https://github.com/openjdk/jdk/blob/jdk-25%2B36/src/hotspot/os/posix/">https://github.com/openjdk/jdk/blob/jdk-25%2B36/src/hotspot/os/posix/</a>
os_posix.cpp#L2091
<br>
<br>
But glibc calls abort() and apparently doesn't generate the
coredump.
<br>
<br>
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:
<br>
<a class="moz-txt-link-freetext" href="https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug/">https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug/</a>
commit/891969416579c7d6a8df6f3b10007a7c78f8ae61
<br>
<br>
The relevant code:
<br>
<br>
//
src/main/kotlin/com/example/demo/controller/CrashController.kt
<br>
...
<br>
@RequestMapping("/crash")
<br>
class CrashController {
<br>
@GetMapping("/abort")
<br>
fun crashWithAbort(): String {
<br>
return NativeCrasher.crashWithAbort()
<br>
}
<br>
...
<br>
<br>
<br>
//
src/main/kotlin/com/example/demo/native/NativeCrasher.kt
<br>
...
<br>
object NativeCrasher {
<br>
init {
<br>
LibraryLoader.load()h
<br>
}
<br>
external fun crashWithAbort(): String
<br>
...
<br>
<br>
<br>
// src/main/c/native_crasher.c
<br>
...
<br>
JNIEXPORT void JNICALL
Java_com_example_demo_native_NativeCrasher_crashWithAbort
<br>
(JNIEnv *env, jobject obj)
<br>
{
<br>
abort();
<br>
}
<br>
...
<br>
<br>
If I hit the endpoint with JDK25:
<br>
<br>
curl localhost:8080/crash/abort
<br>
<br>
I don't get any coredump from that but only this exit code:
<br>
<br>
exited with code 133
<br>
</blockquote>
<br>
That indicates the process terminated via SIGTRAP not SIGABRT.
<br>
<blockquote type="cite">The PoC repository uses docker and
everything is pretty standard apart </blockquote>
<br>
I have a suspicion that it is the Docker environment that is
causing the problem.
<br>
<br>
David
<br>
-----
<br>
<br>
<blockquote type="cite">from the optional patched compilation of
the JVM to register the SIGABRT handler:
<br>
<a class="moz-txt-link-freetext" href="https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug/">https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug/</a>
blob/891969416579c7d6a8df6f3b10007a7c78f8ae61/Dockerfile
<br>
<br>
FROM amazoncorretto:25 AS amazoncorretto-25
<br>
#FROM amazoncorretto-25-patched AS amazoncorretto-25 # Use
this instead to use the patched JVM
<br>
<br>
FROM amazoncorretto-25
<br>
<br>
WORKDIR /app
<br>
<br>
# Copy built JAR from builder
<br>
COPY --from=builder /build/build/libs/*.jar app.jar
<br>
<br>
# Expose port
<br>
EXPOSE 8080
<br>
<br>
# Run application
<br>
ENTRYPOINT ["java", "-jar", "app.jar"]
<br>
<br>
<br>
Álvaro
<br>
<br>
<br>
On 16/2/26 22:33, David Holmes wrote:
<br>
<blockquote type="cite">On 16/02/2026 9:27 pm, Álvaro Torres
Cogollo wrote:
<br>
<blockquote type="cite">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.
<br>
<br>
Based on this stackoverflow post:
<br>
<a class="moz-txt-link-freetext" href="https://stackoverflow.com/a/151568">https://stackoverflow.com/a/151568</a>
<br>
<br>
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.
<br>
</blockquote>
<br>
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.
<br>
<br>
So my question remains: why is the call to abort() not
triggering a coredump?
<br>
<br>
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?
<br>
<br>
David
<br>
------
<br>
<blockquote type="cite">Álvaro
<br>
<br>
<br>
On 16/2/26 11:41, David Holmes wrote:
<br>
<blockquote type="cite">On 13/02/2026 7:25 pm, Álvaro
Torres Cogollo wrote:
<br>
<blockquote type="cite">Hi,
<br>
<br>
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.
<br>
</blockquote>
<br>
My query is: how is it calling abort but not getting a
coredump?
<br>
<br>
David
<br>
<blockquote type="cite">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.
<br>
<br>
Regards,
<br>
<br>
Álvaro
<br>
<br>
<br>
On 13/2/26 08:07, David Holmes wrote:
<br>
<blockquote type="cite">Hi,
<br>
<br>
On 13/02/2026 3:16 am, Álvaro Torres Cogollo wrote:
<br>
<blockquote type="cite">Hi again,
<br>
<br>
I just realized that I made a typo in the
reproduction repository link. This is the right
one:
<br>
<br>
<a class="moz-txt-link-freetext" href="https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug">https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug</a>
<br>
<br>
Sorry about that.
<br>
<br>
Álvaro
<br>
<br>
<br>
On 12/2/26 18:04, Álvaro Torres Cogollo wrote:
<br>
<blockquote type="cite">Hi,
<br>
<br>
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.
<br>
</blockquote>
</blockquote>
<br>
This is the right place (hotspot-runtime-dev would
also have done but a narrower audience).
<br>
<br>
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.
<br>
<br>
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.
<br>
<br>
Need to hear what other think about this.
<br>
<br>
Cheers,
<br>
David
<br>
-----
<br>
<br>
<blockquote type="cite">
<blockquote type="cite">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.
<br>
<br>
Here's what we're seeing when it crashes:
<br>
munmap_chunk(): invalid pointer
<br>
<br>
Or when using tcmalloc:
<br>
src/tcmalloc.cc:333] Attempt to free
invalid pointer 0xffff38000b60
<br>
<br>
We're running with:
<br>
JAVA_TOOL_OPTIONS=-XX:+CreateCoredumpOnCrash -
XX:ErrorFile=/ core-dumps/hs_err_pid%p.log
<br>
<br>
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.
<br>
<br>
After digging through the hotspot source, I
noticed that signal handlers are installed for
SIGSEGV, SIGBUS, SIGFPE, etc., but not for
SIGABRT:
<br>
<br>
<a class="moz-txt-link-freetext" href="https://github.com/openjdk/jdk/">https://github.com/openjdk/jdk/</a>
blob/37dc1be67d4c15a040dc99dbc105c3269c65063d/src/hotspot/os/
posix/ signals_posix.cpp#L1352-L1358
<br>
<br>
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.
<br>
<br>
To demonstrate the issue, I put together a small
reproduction case:
<br>
<br>
<a class="moz-txt-link-freetext" href="https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump">https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump</a>- handling
<br>
<br>
The repo has a Spring Boot app with three
endpoints that show the problem:
<br>
<br>
1. /crash/unsafe - Uses Java Unsafe to write to
address 0
<br>
Result: SIGSEGV -> Works correctly,
generates hs_err file
<br>
<br>
2. /crash/null - JNI code that dereferences a
null pointer
<br>
Result: SIGSEGV -> Works correctly,
generates hs_err file
<br>
<br>
3. /crash/free - JNI code that calls free() on a
stack variable
<br>
Result: SIGABRT -> BROKEN, just prints
"munmap_chunk(): invalid pointer" and dies
<br>
<br>
You can reproduce it with:
<br>
docker-compose up -d
<br>
curl localhost:8080/crash/free
<br>
docker-compose logs
<br>
<br>
And you'll see it just prints the error and
exits, no hs_err file gets created.
<br>
<br>
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:
<br>
<br>
<a class="moz-txt-link-freetext" href="https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug/">https://github.com/atorrescogollo/poc-jdk-sigabrt-coredump-bug/</a> blob/
main/jdk17.patch
<br>
<br>
- Adds set_signal_handler(SIGABRT) in
signals_posix.cpp
<br>
- Resets SIGABRT to SIG_DFL before calling
abort() in os_posix.cpp to avoid recursive
handling
<br>
<br>
After applying it, the /crash/free endpoint
generates proper diagnostics:
<br>
# SIGABRT (0x6) at pc=0x0000ffffbd177608
(sent by kill), pid=1, tid=41
<br>
# Problematic frame:
<br>
# C [libc.so.6+0x87608]
<br>
# Core dump will be written. Default
location: //core
<br>
# An error report file with more
information is saved as:
<br>
# /core-dumps/java_error1.log
<br>
<br>
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.
<br>
<br>
Thanks,
<br>
<br>
Álvaro
<br>
<br>
</blockquote>
</blockquote>
<br>
</blockquote>
</blockquote>
<br>
</blockquote>
</blockquote>
---
<br>
<br>
</blockquote>
</blockquote>
<br>
</blockquote>
<br>
</blockquote>
</body>
</html>