Как я могу отключить встроенный JRuby в ответ на SIGTERM для процесса JVM?
Я запускаю сервер Middleman (который использует Webrick) на JRuby внутри процесса JVM с использованием API org.jruby.embed.ScriptingContainer
.
Если я завершу работу и остановил сервер изнутри JVM, все будет работать так, как ожидалось.
Но если я отправлю SIGTERM в JVM-процесс (например, нажав Ctrl + C в командной строке), консоль вернется, но процесс JVM не завершится - он висит бесконечно, пока я не отправлю его SIGKILL.
Я попробовал зарегистрировать JVM-заглушку для завершения экземпляра ScriptingContainer
, но хук никогда не срабатывает. Я не знаю, почему... возможно, JRuby каким-то образом глотает SIGTERM?
Как я могу заставить JVM полностью закрыть путь, даже если он содержит запущенный сервер Webrick?
Ответы
Ответ 1
Похоже, что kill -9
не вызывает shutdownHook, но kill -15
делает.
fooobar.com/questions/48198/... содержит подробный ответ на ту же проблему.
Нижняя строка: вы ввернуты, поскольку, похоже, не существует способа перехватить сигнал kill -9
и выполнять некоторые задачи обслуживания до остановки JVM.
Ответ 2
Во-первых, отладочный трюк: вы можете отправить SIGQUIT
в процесс Java, чтобы он смог распечатать текущие трассировки стека всех запущенных потоков. Это может помочь вам определить, какие потоки приводят к невозможности выхода JVM.
Отправка SIGINT
, SIGHUP
или SIGTERM
приводит к тому, что Java запускает свои выключения, а затем завершает работу. Вы можете увидеть это в java.lang.Terminator
. После получения сигнала java.lang.Shutdown
обрабатывает все завершающие крючки перед завершением процесса. Shutdown.halt()
не вызывается до тех пор, пока все завершающие крючки не закончатся, что говорит о том, что у вас есть крюк отключения, который висит.
Без реальных трассировок кода или стека трудно дать более точный ответ, но JVM, который остается живым после отправки SIGINT
, обычно делает что-то странное в своих запирающих крючках. Если этого недостаточно, попробуйте отправить SIGINT
, ожидая несколько секунд, затем отправив SIGQUIT
и добавив результирующие трассировки стека к вопросу.