Linux 中多线程的信号处理
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11679568/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Signal handling with multiple threads in Linux
提问by
In Linux, what happens when a program (that possibly has multiple threads) receives a signal, like SIGTERM or SIGHUP?
在 Linux 中,当一个程序(可能有多个线程)收到一个信号时会发生什么,比如 SIGTERM 或 SIGHUP?
Which thread intercepts the signal? Can multiple threads get the same signal? Is there a special thread dedicated entirely to handling signals? If not, what happens inside the thread that is to handle the signal? How does the execution resume after the signal handler routine finishes?
哪个线程拦截信号?多个线程可以得到相同的信号吗?是否有专门用于处理信号的特殊线程?如果不是,在处理信号的线程内部会发生什么?信号处理程序完成后如何恢复执行?
采纳答案by Alan
This is slightly nuanced, based on which version of the Linux kernel you are using.
这有点微妙,具体取决于您使用的 Linux 内核版本。
Assuming 2.6 posix threads, and if you are talking about the OS sending SIGTERM or SIGHUP, the signal is sent to process, which is received by and handled by root thread. Using POSIX threads, you can also sent SIGTERM to individual threads as well, but I suspect you are asking about what happens when the OS sends the signal to the process.
假设 2.6 posix 线程,如果您正在谈论操作系统发送 SIGTERM 或 SIGHUP,则信号被发送到进程,由根线程接收和处理。使用 POSIX 线程,您也可以将 SIGTERM 发送到单个线程,但我怀疑您在询问操作系统将信号发送到进程时会发生什么。
In 2.6, SIGTERM will cause child threads to exit "cleanly", where as 2.4, child threads were left in an indeterminate state.
在 2.6 中,SIGTERM 将导致子线程“干净地”退出,而在 2.4 中,子线程处于不确定状态。
回答by sarnold
pthreads(7)
describes that POSIX.1 requires all threads in a process share attributes, including:
pthreads(7)
描述了 POSIX.1 要求进程中的所有线程共享属性,包括:
- signal dispositions
- 信号处理
POSIX.1 also requires some attributes to be distinctfor each thread, including:
POSIX.1 还要求每个线程的一些属性不同,包括:
signal mask (
pthread_sigmask(3)
)alternate signal stack (
sigaltstack(2)
)
信号掩码 (
pthread_sigmask(3)
)交替信号栈 (
sigaltstack(2)
)
The Linux kernel's complete_signal
routine has the following code block -- the comments are quite useful:
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_GROUP_EXIT) &&
!sigismember(&t->real_blocked, sig) &&
(sig == SIGKILL || !p->ptrace)) {
/*
* This signal will be fatal to the whole group.
*/
So, you see that youare in charge of where signals are delivered:
因此,您会看到您负责信号的传递位置:
If your process has set a signal's disposition to SIG_IGN
or SIG_DFL
, then the signal is ignored (or default -- kill, core, or ignore) for all threads.
如果您的进程已将信号的处置设置为SIG_IGN
或SIG_DFL
,则所有线程都将忽略(或默认——kill、core 或 ignore)该信号。
If your process has set a signal's disposition to a specific handler routine, then you can control which thread will receive the signals by manipulating specific thread signal masks using pthread_sigmask(3)
. You can nominate one thread to manage them all, or create one thread per signal, or any mixture of these options for specific signals, or you rely on the Linux kernel's current default behavior of delivering the signal to the main thread.
如果您的进程已将信号的处置设置为特定的处理程序例程,则您可以通过使用pthread_sigmask(3)
. 您可以指定一个线程来管理它们,或者为每个信号创建一个线程,或者为特定信号创建这些选项的任意组合,或者您依赖 Linux 内核当前将信号传递到主线程的默认行为。
Some signals, however, are special according to the signal(7)
man page:
但是,根据signal(7)
手册页,有些信号是特殊的:
A signal may be generated (and thus pending) for a process as a whole (e.g., when sent using kill(2)) or for a specific thread (e.g., 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.
可以为整个进程(例如,使用kill(2)发送时)或特定线程(例如,某些信号,例如 SIGSEGV 和 SIGFPE,作为执行的结果而生成)生成(并因此挂起)信号特定的机器语言指令是线程导向的,就像使用pthread_kill(3)以特定线程为目标的信号一样 。进程导向的信号可以被传递到当前没有阻塞信号的线程中的任何一个。如果多个线程的信号被解除阻塞,那么内核会选择一个任意线程来传递信号。