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);
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]