<!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>