java - Java 7 Hotspot JVM 是否在 Linux 上使用 SIGRT*?

标签 java linux multithreading signals

我们有一个在 Linux 上的 native 守护进程中加载​​的 java 服务。这个守护进程会阻塞大多数信号并安装自己的信号处理程序,因为这个进程是一个通用的关键任务应用程序。这也是一个多线程应用程序,它大量利用了 pthreads,并且 HotSpot JVM 被加载到其中一个线程中。

在 64 位 Linux(SLES、RH)上升级到 Java 7 JVM 后,我们注意到等待连接的 ServerSocket 在套接字关闭时没有收到信号。根据 JavaDoc ,当前在 accept() 中阻塞的任何线程都将抛出 SocketException,这样我们在服务关闭时关闭监听套接字。我们怀疑我们在 native 进程中处理信号的方式,因为我们多年前有过类似的经历,结果证明是正确的。

在我们的 native 进程中,我们按如下所示(伪代码)阻止信号。我们确实使用下面未显示的 sigaction() 安装我们自己的处理程序。

sigset_t    set;
sigfillset(&set);
sigdelset(&set, SIGTRAP);
sigdelset(&set, SIGSEGV);

/* Remove following signals as it appears to be used by JVM */
for (int s = SIGRTMIN; s <= SIGRTMAX-4; s++) {
    sigdelset(&set, s);
}

if ((err = pthread_sigmask(SIG_BLOCK, &set, 0)) != 0) {
    err_warn(“Unable to block signals: %d”, err);
}

/* pthread_create() for LoadJVM calls and continue. 
   Threads are detached and hence no join()          */

/* Read current mask */
pthread_sigmask(SIG_BLOCK, 0, &set);

/* Wait on these signals */

while (bshutdown == false) {
    if ((sig = sigwaitinfo(&set, &info)) == -1) {
        /* something unexpected happened */
    }
    switch (sig) {
        /* Do something */
    }
}

我们在新的 JVM 中发现,如果我们从集合中删除 SIGRTMAX-2 和 SIGRTMAX-3,Java ServerSockets 在关闭时不会收到通知。目前,我们在加载JVM的线程中添加这两个信号并调用pthread_sigmask(SIG_UNBLOCK, &set, 0)来解决问题。

我的问题是:

  1. 有谁知道 JVM 是否使用这些信号。 JavaDoc on handling signals 没有列出它们。
  2. 在 Linux 上(在 x86_64 内核 2.6.32 上测试, 3.11.6),读取当前信号掩码 (pthread_sigmask(SIG_UNBLOCK, 0, &set)) 不返回当前掩码。 set 只是 0。有 有人见过这种行为吗?它在 OSX 和 Solaris 上运行良好。

最佳答案

感谢您建议使用 strace。虽然我使用 strace 来查看 JVM 是如何阻塞信号的,但我并没有考虑检查套接字是如何关闭的。这是我发现的..

[pid  5525] rt_sigprocmask(SIG_BLOCK, [QUIT], NULL, 8) = 0
========== Waiting for 30 sec before shutdown ==========
========== IP : 0.0.0.0, Port : 9999 ==========
[pid  5525] rt_sigaction(SIGRT_30, {0x7f8844015200, [], SA_RESTORER, 0x7f884de779f0}, NULL, 8) = 0
[pid  5525] rt_sigprocmask(SIG_UNBLOCK, [RT_30], NULL, 8) = 0
========== Shutting down ==========
[pid  5516] tgkill(5515, 5525, SIGRT_30 <unfinished ...>
[pid  5525] --- SIGRT_30 {si_signo=SIGRT_30, si_code=SI_TKILL, si_pid=5515, si_uid=1000} ---
[pid  5525] rt_sigreturn()              = -1 EINTR (Interrupted system call)
[pid  5516] <... tgkill resumed> )      = 0

这意味着,SIGRT_30 (SIGRTMAX_2) 在监听套接字关闭时向其发出信号。

关于java - Java 7 Hotspot JVM 是否在 Linux 上使用 SIGRT*?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20536386/

相关文章:

java - Twitter4j Google App Engine - java.lang.NoClassDefFoundError

Python从线程结束父进程

java - 如何将一个大数组列表分解为 HashMap 中的多个数组列表?

java - 在Java中使用POI获取Excel单元格背景颜色不匹配

linux - 如何编译生成.exe?

linux - 有没有办法在 ZLinux 上编写 IBM 的 BAL?

python - Barebones SWIG python C 接口(interface)在 OSX+clang 上出现段错误,而不是在 Linux+gcc 中

c++ - 哪些因素应该决定我的 C++ 网络服务器上的线程数?

asp.net - ASP.NET 工作线程可以一次处理多个请求吗?

java - 单击按钮后重新绘制 JPanel