1

假设您处于单线程进程中,并且相关信号未被阻止或忽略,是否可以保证:

kill(getpid(), sig);

会导致在执行下一行代码之前传递信号吗?

特别是,如果信号是一个没有处理程序的信号并且整个默认操作是终止进程(例如SIGTERM,SIGALRM),是否保证不会执行下一行代码?

我一直认为(至少在 Linux 上)答案是“是”,因为我认为在从任何系统调用返回之前,内核总是会检查是否有任何未决的信号,如果有,则传递它们。但我我已经观察到(当在重负载的多核系统上运行时)情况并非总是如此,尽管这很难重现,所以我很感激确认我没有看到任何东西。

[这个问题非常类似于Is a signal sent with kill to a parent thread是否保证在下一条语句之前被处理?除了那个问题是关于多线程进程的问题(答案肯定是“否”),而这个问题是关于单线程进程的。]

4

3 回答 3

0

我现在认为答案确实是“是”。我之前以为信号没有被阻塞,但我现在意识到情况可能并非如此,这很可能是我所看到的行为的原因。

于 2012-06-28T16:07:48.497 回答
0

是的。如果您处于单线程进程中,POSIX 会向您保证这一点

如果 pid 的值导致为发送进程生成 sig,并且如果没有为调用线程阻塞 sig,并且如果没有其他线程已解除阻塞 sig 或在 sigwait() 函数中等待 sig,则 sig 或至少在 kill() 返回之前,应将一个未决的未阻塞信号传递给发送线程。

于 2017-11-16T11:40:29.633 回答
0

我做了这个测试代码:

#include <signal.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>

sig_atomic_t suspended = 0;

void handle() {
    printf("SIG");
}

int main(int argc, char **argv) {
    signal(SIGUSR1, handle);
    printf("BEFO");
    kill(getpid(), SIGUSR1);
    //pthread_kill(pthread_self(), SIGUSR1);
    printf("AFTR\n");
    return 0;
}

当我在 4 核笔记本电脑上的 bash 循环中运行它时,它似乎总是打印 BEFOSIGAFTR 而从不打印 BEFOAFTRSIG。

但请注意,该测试在几个方面存在相当大的缺陷:

  • 事实上它在我的电脑上工作并不意味着它是有保证的(除非它在 ​​POSIX 文档中说明)
  • 系统在测试期间没有承受重负载
  • STDIO 做一些缓冲
  • printf() 不是信号安全的(man 7 signal-safety)
于 2021-06-29T09:10:04.260 回答