Java 中关于信号的处理在Linux下的实现
Linux 的线程和信号
基于 NPTL 的线程库,多线程应用中的每个线程有自己独特的线程 ID,并共享同一个进程ID。应用程序可以通过调用<font face="Courier New"> kill(getpid(),signo)</font>
将信号发送到进程,如果进程中当前正在执行的线程没有阻碍此信号,则会被中断,线号处理函数会在此线程的上下文背景中执行。应用程序也可以通过调用<font face="Courier New"> pthread_kill(pthread_t thread, int sig)</font>
将信号发送给指定的线程,则线号处理函数会在此指定线程的上下文背景中执行。
Java里信号掩码的集合
unblocked_sigs | SIGILL SIGSEGV SIGBUS SIGFPE SR_signum SHUTDOWN1_SIGNAL(SIGHUP) SHUTDOWN2_SIGNAL(SIGINT) SHUTDOWN3_SIGNAL(SIGTERM) |
vm_sigs | BREAK_SIGNAL (SIGQUIT) |
allowdebug_blocked_sigs | SHUTDOWN1_SIGNAL(SIGHUP) SHUTDOWN2_SIGNAL(SIGINT) SHUTDOWN3_SIGNAL(SIGTERM) |
SIG_BLOCK | NULL |
在多线程的应用中,每个线程可以通过调用pthread_signmask()设置本线程的信号掩码,可以设置阻塞的信号,但信号SIGKILL/SIGSTOP是不能被设置成阻塞的。
在java中,每个线程都设置了在表格中的信号掩码,特别提到的是vm_sigs,这是只有一个quit 的信号结合,当没有设置启动参数 -Xrs (=ReduceSignalUsage)的时候,其他的线程设置成阻塞的,除了vm thread。
- void os::Linux::hotspot_sigmask(Thread* thread) {
- //Save caller's signal mask before setting VM signal mask
- sigset_t caller_sigmask;
- pthread_sigmask(SIG_BLOCK, NULL, &caller_sigmask);
- OSThread* osthread = thread->osthread();
- osthread->set_caller_sigmask(caller_sigmask);
- pthread_sigmask(SIG_UNBLOCK, os::Linux::unblocked_signals(), NULL);
- if (!ReduceSignalUsage) {
- if (thread->is_VM_thread()) {
- // Only the VM thread handles BREAK_SIGNAL ...
- pthread_sigmask(SIG_UNBLOCK, vm_signals(), NULL);
- } else {
- // ... all other threads block BREAK_SIGNAL
- pthread_sigmask(SIG_BLOCK, vm_signals(), NULL);
- }
- }
- }