在Linux中使用多个线程进行信号处理

113 c linux multithreading signals ipc

在Linux中,当程序(可能有多个线程)收到SIGTERM或SIGHUP等信号时会发生什么?

哪个线程截获信号?多个线程可以获得相同的信号吗?是否有专门用于处理信号的特殊线程?如果没有,那么处理信号的线程内部会发生什么?信号处理程序例程结束后如何恢复执行?

sar*_*old 125

pthreads(7) 描述POSIX.1要求进程共享属性中的所有线程,包括:

  • 信号处理

POSIX.1也需要一些属性是不同的每个线程,包括:

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.
         */
Run Code Online (Sandbox Code Playgroud)

所以,你看到负责传递信号的地方:

如果你的过程中树立了信号的处置SIG_IGNSIG_DFL所有线程- ,则信号被忽略(杀,核心,或忽略或默认).

如果你的过程中树立了信号的配置到一个特定的处理程序,那么你就可以控制哪个线程将通过操纵特定线程的信号掩码接收信号pthread_sigmask(3).您可以指定一个线程来管理它们,或者为每个信号创建一个线程,或者为特定信号创建这些选项的任何混合,或者您依赖于Linux内核当前将信号传递到主线程的默认行为.

但是,根据signal(7)手册页,某些信号是特殊的:

可以为整个过程(例如,当使用kill(2)发送时)或针对特定线程(例如,由于执行而生成的某些信号,例如SIGSEGV和SIGFPE )生成(并因此待决)信号.特定的机器语言指令是线程指向的,使用pthread_kill(3)针对特定线程的信号也是如此 .可以将过程引导的信号传递到当前没有阻塞信号的任何一个线程.如果多个线程的信号未被阻塞,则内核选择一个任意线程来传递信号.


Ala*_*lan 35

根据您使用的Linux内核版本,这有点细微差别.

假设2.6 posix线程,并且如果您正在讨论发送SIGTERM或SIGHUP的OS,则将信号发送到进程,该进程由根线程接收并由其处理.使用POSIX线程,您也可以将SIGTERM发送到各个线程,但我怀疑您询问操作系统将信号发送到进程时会发生什么.

在2.6,SIGTERM会导致子线程退出"干净",其中2.4,子线程都处于不确定状态离开.

  • 我对"根线程"的含义感到有些困惑.这是否意味着SIGTERM的处理程序将始终在主线程中运行,还是可以在任何线程中运行? (9认同)
  • [此答案](/sf/answers/1540407431/),其中指出选择了任意线程来处理信号,这与您的答案相矛盾。 (5认同)