Как VM_Exit доставляется в VM Thread при отправке SIGTERM и кто осуществляет доставку? - PullRequest
0 голосов
/ 01 июля 2019

Я пытаюсь понять, как точка доступа JVM обрабатывает сигналы завершения (например, SIGTERM). Что я мог найти, так это то, что расположение сигнала SIGTERM установлено в этой точке на UserHandler, что выглядит (комментарии опущены):

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

Таким образом, все, что он делает, это уведомляет Signal Dispatcher и устанавливает номер принятого сигнала на static volatile jint pending_signals[NSIG+1].

Но в случае SIGTERM фактическое exit(143) делается в VM Thread. Задача VM_Exit с _exit_code = 143 каким-то образом доставляется в VM Thread.

Вопрос: Можете ли вы дать подсказку, кто сгенерирует эту задачу VM_Exit и отправит ее на VM Thread позже? Меня особенно беспокоит то, как для 143 установлено значение VM_Exit::_exit_code?

Я запустил JVM HotSpot под GDB со следующим основным классом:

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

И не нашел, что Signal Dispatcher отправлял задачу VM_Exit. Прекращение произошло в этом заявлении :

JavaCalls::call_virtual(&result,
                        threadObj, thread_klass,
                        vmSymbols::exit_method_name(),
                        vmSymbols::void_method_signature(),
                        THREAD);

1 Ответ

2 голосов
/ 01 июля 2019

SIGTERM, SIGINT и SIGHUP обрабатываются в Java-коде из java.lang.Terminator.

Одна из менее известных функций async-profiler заключается в том, что он может профилировать произвольные собственные функции и показывать смешанные собственные стеки Java +.Например, если вы хотите перехватить JVM_Halt и посмотреть, как Java-код его называет, запустите

$ 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]
...