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

2022-09-02 02:04:02

我正在使用API在JRuby的JVM进程内运行一个中间人(使用Webrick)服务器。org.jruby.embed.ScriptingContainer

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

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

我尝试注册 JVM 关闭挂钩来终止实例,但挂钩从未触发。我不知道为什么...也许JRuby正在以某种方式吞下SIGTERM?ScriptingContainer

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


答案 1

看起来不会触发关机Hook,但会触发。kill -9kill -15

此 StackOverflow 问题对同一问题有详细的答案。

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


答案 2

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

发送 、 或 使 Java 运行其关闭挂钩,然后退出。你可以在java.lang.Terminator中看到这一点。一旦收到信号,java.lang.shutdown 就会在终止进程之前处理所有 shutdown 钩子的运行。 直到关闭挂钩全部完成后才会调用,这表明您有一个已关闭挂钩挂起。SIGINTSIGHUPSIGTERMShutdown.halt()

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


推荐