Linux中的multithreading信号处理
在Linux中,当一个程序(可能有多个线程)接收到SIGTERM或SIGHUP信号时会发生什么?
哪个线程拦截信号? 多个线程可以得到相同的信号? 是否有一个专门处理信号的专用线程? 如果不是的话,在处理信号的线程中会发生什么? 信号处理程序完成后,执行过程如何恢复?
根据所使用的Linux内核版本的不同,这有些微妙之处。
假设有2.6个posix线程,如果你正在谈论发送SIGTERM或者SIGHUP的操作系统,那么这个信号被发送到进程,由进程接收并由根进程处理。 使用POSIX线程,您也可以将SIGTERM发送到单个线程,但是我怀疑您是在询问操作系统向进程发送信号时会发生什么。
在2.6中,SIGTERM将导致子线程“干净地”退出,其中2.4子线程处于不确定状态。
pthreads(7)
描述了POSIX.1要求进程中的所有线程共享属性,包括:
- 信号configuration
POSIX.1还要求每个线程都具有不同的属性,其中包括:
-
信号掩码(
pthread_sigmask(3)
) -
备用信号堆栈(
sigaltstack(2)
)
Linux内核的complete_signal()
例程具有以下代码块 – 注释非常有用:
/* * Now find a thread we can wake up to take the signal off the queue. * * If the main thread wants the signal, it gets first crack. * Probably the least surprising to the average bear. */ if (wants_signal(sig, p)) t = p; else if (!group || thread_group_empty(p)) /* * There is just one thread and it does not need to be woken. * It will dequeue unblocked signals before it runs again. */ return; else { /* * Otherwise try to find a suitable thread. */ t = signal->curr_target; while (!wants_signal(sig, t)) { t = next_thread(t); if (t == signal->curr_target) /* * No thread needs to be woken. * Any eligible threads will see * the signal in the queue soon. */ return; } signal->curr_target = t; } /* * Found a killable thread. If the signal will be fatal, * then start taking the whole group down immediately. */ if (sig_fatal(p, sig) && !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) && !sigismember(&t->real_blocked, sig) && (sig == SIGKILL || !t->ptrace)) { /* * This signal will be fatal to the whole group. */
所以,你看到你负责信号的传递:
如果您的进程已经将信号设置为SIG_IGN
或SIG_DFL
,那么对于所有线程,该信号将被忽略(或默认 – kill,core或ignore)。
如果你的进程已经设置了一个特定的处理函数的信号处理,那么你可以通过使用pthread_sigmask(3)
来操纵特定的线程信号掩码来控制哪个线程将接收信号。 您可以指定一个线程来pipe理它们,或者为每个信号创build一个线程,或者为这些特定的信号创build这些选项的任意组合,或者依靠Linux内核当前将信号传递到主线程的默认行为。
有些信号是特殊的:
A signal may be generated (and thus pending) for a process as a whole (eg, when sent using kill(2)) or for a specific thread (eg, certain signals, such as SIGSEGV and SIGFPE, generated as a consequence of executing a specific machine- language instruction are thread directed, as are signals targeted at a specific thread using pthread_kill(3)). A process-directed signal may be delivered to any one of the threads that does not currently have the signal blocked. If more than one of the threads has the signal unblocked, then the kernel chooses an arbitrary thread to which to deliver the signal.