如何干净地关闭嵌入式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无法退出。

发送SIGINTSIGHUPSIGTERM会导致Java运行其关闭挂钩,然后退出。 你可以在java.lang.Terminator看到这个。 收到信号后, java.lang.Shutdown在终止进程之前处理所有关闭挂钩的运行。 直到关闭挂钩全部完成后才会调用Shutdown.halt() ,这表示你有一个挂起的挂钩。

如果没有实际的代码或堆栈跟踪,很难提供比这更精确的答案,但是在发送SIGINT之后保持活动的JVM通常在其关闭挂钩中做一些奇怪的事情。 如果这还不足以继续尝试发送一个SIGINT ,等待几秒钟,然后发送一个SIGQUIT ,并将结果堆栈跟踪添加到问题中。