如何干净地关闭嵌入式JRuby以响应SIGTERM到JVM进程?
我正在使用org.jruby.embed.ScriptingContainer
API在JVM进程内运行JRuby上的Middleman(使用Webrick)服务器。
如果我干净地关闭并从JVM内部停止服务器,一切都按预期工作。
但是如果我将一个SIGTERM发送到JVM进程(例如,通过在命令行中按ctrl + C),控制台将返回但JVM进程不会终止 – 它会无限期地挂起,直到我发送一个SIGKILL。
我尝试注册一个JVM关闭钩子来终止ScriptingContainer
实例,但钩子永远不会触发。 我不确定为什么……也许JRuby以某种方式吞下了SIGTERM?
即使它包含正在运行的Webrick服务器,如何让JVM完全关闭,干净利落地关闭?
看起来像kill -9
不会触发shutdownHook,但kill -15
会触发。
StackOverflow问题对此问题有详细解答。
最重要的是,你被搞砸了,因为似乎没有任何方法可以拦截kill -9
信号并在JVM停止之前执行一些维护任务。
首先,一个调试技巧:您可以将SIGQUIT
发送到Java进程,以使其打印所有正在运行的线程的当前堆栈跟踪。 这可以帮助您诊断哪些线程导致JVM无法退出。
发送SIGINT
, SIGHUP
或SIGTERM
会导致Java运行其关闭挂钩,然后退出。 你可以在java.lang.Terminator
看到这个。 收到信号后, java.lang.Shutdown
在终止进程之前处理所有关闭挂钩的运行。 直到关闭挂钩全部完成后才会调用Shutdown.halt()
,这表示你有一个挂起的挂钩。
如果没有实际的代码或堆栈跟踪,很难提供比这更精确的答案,但是在发送SIGINT
之后保持活动的JVM通常在其关闭挂钩中做一些奇怪的事情。 如果这还不足以继续尝试发送一个SIGINT
,等待几秒钟,然后发送一个SIGQUIT
,并将结果堆栈跟踪添加到问题中。