c - Linux 中多线程的信号处理

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

哪个线程拦截了信号?多个线程可以得到相同的信号吗?是否有专门用于处理信号的特殊线程?如果不是,处理信号的线程内部会发生什么?信号处理程序完成后如何恢复执行?

最佳答案

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

  • 信号配置

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_GROUP_EXIT) &&
    !sigismember(&t->real_blocked, sig) &&
    (sig == SIGKILL || !p->ptrace)) {
        /*
         * This signal will be fatal to the whole group.
         */

因此,您会看到 负责信号的传递位置:

如果您的进程已将信号的处置设置为 SIG_IGNSIG_DFL,则所有线程都会忽略该信号(或默认 -- kill、core 或 ignore) .

如果您的进程已将信号的处置设置为特定的处理程序例程,那么您可以通过使用 pthread_sigmask(3) 操作特定线程信号掩码来控制哪个线程将接收信号。 .您可以指定一个线程来管理所有这些,或者为每个信号创建一个线程,或者这些选项的任意组合用于特定信号,或者您依赖 Linux 内核当前将信号传递到主线程的默认行为。

然而,根据 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.

https://stackoverflow.com/questions/11679568/

相关文章:

python - 在进程运行时不断打印子进程输出

python - Django 1.7 抛出 django.core.exceptions.AppR

python - 如何搜索和替换文件中的文本?

python - 如何访问 Django 模板中的字典元素?

android - 找不到构建工具修订版 23.0.1

linux - 查找 -exec cmd {} + vs | xargs

linux - 如何让 CRON 调用正确的路径

linux - 每个虚拟主机的error_log?

python - 如何将 python 日期时间转换为具有可读格式日期的字符串?

linux - 如何找出适合由 shell 脚本解析的 linux 机器的总物理内存 (RAM)?