如何干净地关闭嵌入式JRuby以响应SIGTERM到JVM进程?

时间:2015-04-16 15:00:01

标签: java jvm jruby webrick

我使用org.jruby.embed.ScriptingContainer API在JVM进程内运行JRuby上的Middleman(使用Webrick)服务器。

如果我干净地关闭并从JVM内部停止服务器,一切都按预期工作。

但是如果我将一个SIGTERM发送到JVM进程(例​​如,通过在命令行中按ctrl + C),控制台将返回但JVM进程不会终止 - 它会无限期地挂起,直到我发送一个SIGKILL。

我尝试注册JVM关闭挂钩来终止ScriptingContainer实例,但挂钩永远不会触发。我不知道为什么......也许JRuby不知怎的吞下了SIGTERM?

即使JVM包含正在运行的Webrick服务器,如何让JVM完全关闭呢?

2 个答案:

答案 0 :(得分:1)

看起来kill -9不会触发shutdownHook,但kill -15会触发。{/ p>

This StackOverflow question对同一问题有详细解答。

底线是,你搞砸了,因为在JVM停止之前似乎没有任何方法可以拦截kill -9信号并执行一些维护任务。

答案 1 :(得分:0)

首先,一个调试技巧:您可以将SIGQUIT发送到Java进程,以使其打印所有正在运行的线程的当前堆栈跟踪。这可以帮助您诊断哪些线程导致JVM无法退出。

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

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