0

I'm trying to understand how JVM hotspot handles termination signals (SIGTERM for example). What I could found is that the SIGTERM signal disposition is set at this point to UserHandler which looks as (comments ommitted):

static void UserHandler(int sig, void *siginfo, void *context) {
  if (sig == SIGINT && Atomic::add(1, &sigint_count) > 1) {
    return;
  }
  if (sig == SIGINT && VMError::is_error_reported()) {
    os::die();
  }
  os::signal_notify(sig);
}

So all it does is to notify Signal Dispatcher and set the received signal number to the static volatile jint pending_signals[NSIG+1].

But in case of SIGTERM the actual exit(143) is done in VM Thread. The VM_Exit task with the _exit_code = 143 is somehow delivered to the VM Thread.

Question: Can you give a hint who generates this VM_Exit task and sends it to VM Thread later? I'm particularly concerned about how the 143 is set to VM_Exit::_exit_code?

I ran JVM HotSpot under gdb with the following main class:

public class Main{
    public static void main(String args[]) throws Exception {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("Shutdown hook is called");
        }));
        Thread.sleep(1000000);
    }
}

And did not find that Signal Dispatcher was sending the VM_Exit task. The termination occured at that statement:

JavaCalls::call_virtual(&result,
                        threadObj, thread_klass,
                        vmSymbols::exit_method_name(),
                        vmSymbols::void_method_signature(),
                        THREAD);
Some Name
  • 8,555
  • 5
  • 27
  • 77
  • I noticed this is not your first question where the title completely mismatches the highlighed question. It's hard to understand whether you are interested in the invocation of shutdown hooks (which is done mostly in Java code) or in calling `VM_Exit` which is done at the late phase of JVM termination when no Java code is longer running. – apangin Jul 01 '19 at 16:36
  • @apangin I fixed the title. – Some Name Jul 01 '19 at 16:43
  • @apangin I found that there is `SIGTERM handler` thread invoking [JVM_Halt](https://hg.openjdk.java.net/jdk/jdk12/file/06222165c35f/src/hotspot/share/prims/jvm.cpp#l475) with the code 143. But its invocation is done from the JIT compiled code. Can you give an idea which code does the invocation? – Some Name Jul 01 '19 at 16:51

1 Answers1

2

SIGTERM, SIGINT and SIGHUP are handled in Java code of java.lang.Terminator.

One of the lesser known features of async-profiler is that it can profile arbitrary native functions and show mixed Java+native stacks. E.g. if you want to intercept JVM_Halt and see what Java code calls it, run

$ java -agentpath:/path/to/libasyncProfiler.so=start,traces,threads,event=JVM_Halt Main

Started [JVM_Halt] profiling
^CShutdown hook is called
--- 1 events (100.00%), 1 sample
  [ 0] JVM_Halt
  [ 1] java.lang.Shutdown.halt0
  [ 2] java.lang.Shutdown.halt
  [ 3] java.lang.Shutdown.exit
  [ 4] java.lang.Terminator$1.handle
  [ 5] jdk.internal.misc.Signal$1.run
  [ 6] java.lang.Thread.run
  [ 7] [SIGINT handler tid=19080]
apangin
  • 92,924
  • 10
  • 193
  • 247
  • Is it possible to see such mixed java/native stacktraces in `--enable-debug` build? Or some extra configuration is required? – Some Name Jul 01 '19 at 23:06
  • 1
    @SomeName Yes, there are debug functions like [`ps()`](https://hg.openjdk.java.net/jdk/jdk12/file/06222165c35f/src/hotspot/share/utilities/debug.cpp#l457) that print Java stack trace under gdb. – apangin Jul 01 '19 at 23:42
  • Wow, it prints the exact stacktrace you showed with all addresses. Very cool thing, now it is much easier to understand what is going on when debugging under gdb. Thank you. – Some Name Jul 02 '19 at 08:59