为什么 sigsuspend 在 while 循环中不起作用?

Why sigsuspend does not work in while loop?

我正在尝试了解信号的工作原理。当我将 sigsuspend 放在 while 循环之外时,代码有效,否则无效。为什么?

static void signal_handler(int sig) {
    printf("SIGUSR1 has been received!");
}

int main() {
    struct sigaction sigact;
    sigset_t sigset;
    sigemptyset(&sigset);

    sigact.sa_handler = signal_handler;
    sigact.sa_mask = sigset;
    sigact.sa_flags = 0;

    sigaction(SIGUSR1, &sigact, NULL);

    while(1) {
        sigsuspend(&sigset);
        printf("The signal has been received!");
    }
}

When i put sigsuspend outside of the while loop the code works otherwise it doesn't.

我的意思是,当您将 SIGUSR1 发送到根据所提供的代码构建的程序时,您看不到任何输出。这与循环或信号没有直接关系。问题是标准输出在默认情况下是 buffered —— 当它连接到终端时行缓冲,否则完全缓冲。如果您向进程发送足够多的 SIGUSR1,它最终会打印足够多的输出来填充缓冲区,然后您将看到所有消息。

要立即查看消息,

  • (如果 stdout 连接到终端)在每条消息的末尾添加一个换行符:

    printf("The signal has been received!\n");
    

  • 在每个 printf:

    之后刷新标准输出
     printf("The signal has been received!");
     fflush(stdout);
    

  • 改为将输出定向到 stderr,默认情况下是无缓冲的:

     fprintf(stderr, "The signal has been received!");
    

    甚至

  • 更改标准输出的缓冲模式:

     setvbuf(stdout, NULL, _IONBF, 0);
    

    (一次就够了)

至于为什么你认为当你只调用一次 sigsuspend() 而不是无限循环时你会看到不同的行为,那是因为当程序正常终止时,程序打开的流会自动刷新和关闭。

此外,printf() 不是 async-signal-safe,因此您可以通过从信号处理程序调用它来引发未定义的行为。不要那样做,即使它在某些情况下似乎对你有用。