是否保证kill()函数不会返回,直到信号处理程序完成,如果进程自杀?

时间:2014-12-18 08:31:36

标签: linux signals

想象一下用C编写的以下程序:

void handler(int signo) {
    write(STDOUT_FILENO, "handler\n", 8);
}
int main() {
    signal(SIGUSR1, handler);
    kill(getpid(), SIGUSR1);
    write(STDOUT_FILENO, "after kill\n", 11);
}

如果我在Linux中运行此程序,输出是否可能如下:

after kill
handler

我尝试了很多次,但上面的结果并没有出现。

2 个答案:

答案 0 :(得分:1)

如果在puts("looping");语句之后将SIGINT信号传递给进程,则它将打印字符串" handler1"在handle1函数中。当kill函数返回时,输出取决于SIGUSR1信号何时传递给进程。我认为您可以使用sigsuspend功能来确保它符合您的要求。顺便说一下,在kill函数返回之前,至少有一个未阻塞的信号被传递给进程。

以下代码输出您想要的内容,您需要先阻止SIGUSR1信号。

#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void handler(int signo) {
    write(STDOUT_FILENO, "handler\n", 8);
}
int main() {

    sigset_t newmask, oldmask;
    sigemptyset( &newmask );
    sigaddset( &newmask, SIGUSR1 );

    signal(SIGUSR1, handler);

    // block the SIGUSR1 signal
    sigprocmask ( SIG_BLOCK, &newmask, &oldmask );

    kill(getpid(), SIGUSR1);
    write(STDOUT_FILENO, "after kill\n", 11);

    // reset the signal mask
    sigprocmask ( SIG_SETMASK, &oldmask, NULL );
}

答案 1 :(得分:0)

puts内部信号处理程序不好。阅读signal(7)puts async-signal-safe。您应该在信号处理程序(不是puts)中使用write(2)

您已修改问题以使用write代替puts

如果你坚持错误地使用puts,你至少应该致电fflush。但是在信号处理程序中两者都是错误的。

(不要忘记缓存了stdout

顺便说一下,它可能会发生(特别是在多线程应用程序中,信号处理程序没有在kill(2) - s信号的同一个线程中运行)在返回{{1}之后调用信号处理程序}}

我不确定你是否能保证单线程进程的信号处理程序在kill之前返回,即使我相信大多数Linux内核都会发生这种情况。你应该确定的是信号处理程序最终会被调用(但是 时你无法确定)。此外,允许内核丢失一些信号(例如,如果外部事物或进程正在发送大量相同的信号)。所谓的POSIX real-time信号是例外,而不是常态(另见this

如果你有一个event loop(例如大约poll(2))并接受拥有特定于Linux的代码 您可以考虑使用signalfd(2)并在事件循环中对其进行轮询。