【问题标题】:java application being abrutply terminated on shutdown without having signal sentjava应用程序在关闭时突然终止而没有发送信号
【发布时间】:2014-03-02 13:24:32
【问题描述】:

需要明确的是,这是一个 upstart/linux 调试问题,而不是 java 问题本身。

我有一个安装了shutdownhook 的java 应用程序。它在 ubuntu-GNOME 中显示了一些有趣的行为,即如果安排了重新启动或关闭电源,则关闭挂钩永远不会运行。起初我认为这是我的关闭挂钩的问题,所以我简化了它,直到它只向文件写入一行(是的,我知道关闭挂钩的 log4j2 记录器问题,所以我也禁用了他们的)。然后当这不起作用时,我开始破解 /etc/init/sendsigs

我在 do_stop 函数的开头添加了这个:

app="$(jps | grep appname.jar | cut -d' ' -f1)"
echo "$app" >>  "/home/i30817/output.txt"

果然,这表明它不再运行,因此 sendigs 从未激活关闭挂钩 然后我使用 here 的 lastcomm 将我对 sendigs 的编辑替换为:

echo `/home/i30817/lastcomm` >  "/home/i30817/output.txt"

它告诉我java进程以1退出并且没有发出信号:

java X i30817 ?? 10.26 secs Sun Mar 2 12:44 E 1

但这仍然没有帮助我找到真正杀死它的原因以及原因。使用较小的示例无法重现此问题,因此它可能是较大的应用程序中的某些东西(但不是关闭挂钩,因为它已被最小化)不喜欢关闭过程并设法杀死该过程,但我不能弄清楚...将进程输出重定向到文件也没有说什么,例如:

java -jar /home/i30817/Documents/projects/app/dist/app.jar > allout.text 2>&1 

除了正常的应用程序输出外,什么都没有 你能帮我弄清楚这个吗?关于同一件事也有很多重复的问题(但他们认为这是关闭挂钩出现故障)。

编辑:更详细,现在我更好地理解了这个问题。我认为现在在 sendigs 上没有进程是正常的。 Java 应用程序,可能还有其他应用程序使用来自窗口管理器的协议,其中 SIGHUP、SIGHUP 和 SIGCONT 在关机/注销时发送。 JVM 挂钩 SIGHUP 以启动关闭挂钩。我用一个非常小的例子测试了这个,它只添加了一个shutdownhook并且在main上有一个无限循环,并在后台使用system tap script运行它:

  java -jar app.jar 

在另一个shell中

  sudo stap -o process.txt sigkill.stp

但是,当我尝试使用我的应用程序时,我认为我找到了罪魁祸首:

  PROCESS: SIGSEGV java.signal_generate sent to java 2280

但考虑到没有线程转储或任何东西,我真的不知道该怎么做,而且重现起来很奇怪(仅我的应用程序,仅在关闭期间)。

edit2:现在我怀疑在没有核心转储的情况下“突然”终止的原因是关机期间的 ulimit。因此,我正在尝试解决该问题以准备错误报告。我编辑了 /etc/security/limits.conf 以添加它并重新启动

   *               soft    core            unlimited
   root            hard    core            unlimited
   *               hard    rss             10000

(fs.suid_dumpable=2 是由 ubuntu 设置的,我认为没有 apparmor) 但是在关机期间,我再次编辑 /etc/init.d/sendsigs 以打印 ulimit -a 并在终止进程之前休眠 30 秒,并且似乎在重新启动期间 ulimit 再次重置?此外,它具有不同的输出,就像它使用另一个可执行版本一样,例如,它没有说“核心文件大小”,而是使用“核心(转储)”或类似的东西)。

edit3:啊,我需要改用 fs.suid_dumpable=1 - 现在就试试。 也许 init ulimit 对于关闭核心转储触发无关紧要。毕竟 jvm 是从用户 env 执行的,所以它应该使用用户 ulimit。

edit4:嗯。在对代码进行大量评论后,我得出了以下结论,我可以从 RTFM 中得出:

  1. sigsegv 是无害的。

  2. 非零退出码不是。

如果 AWT 仍处于启动状态,则信号始终为非零且关闭挂钩永远不会运行。如果 JFrame 已启动(与 Windows 不同,它们将在其中启动),即使是一个小示例仍会阻止在 linux 重新启动时执行关闭挂钩。查看源代码,应用程序关闭挂钩是在插槽 1 上自行运行的。我敢打赌,插槽 '0' 是 AWT,它会以某种方式停止系统。

我想是时候检查包私有信号处理库了,看看我是否可以在 JVM 决定终止所有内容之前获得 SIGHUP,甚至没有机会运行清理代码。

【问题讨论】:

  • 您有不同应用程序的来源吗?如果我有这个问题,我会设置 eclipse 来调试服务器端设置断点。我提到这一点是因为您发现 java 进程没有发出信号。
  • 没有不同的应用程序,这都是一个客户端摇摆应用程序。我实际上是通过安排重启来测试这个。我确实有它的来源。
  • @D-Klotz 我在这里发布了一个示例:stackoverflow.com/questions/22262190/…

标签: java linux process shutdown coredump


【解决方案1】:

根据文档

http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)

在极少数情况下,虚拟机可能会中止,即在没有完全关闭的情况下停止运行.... 如果虚拟机中止,则无法保证是否会运行任何关闭挂钩。

【讨论】:

  • 嗯,是的,但我肯定想找出这个可重复的烦人错误的原因。
  • 这与 EDT 和 Gnome3 在关机时更加激进有关。
猜你喜欢
  • 2020-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-25
相关资源
最近更新 更多