在Linux上测试SIGINT和SIGHUP时有趣的类似故障的行为

时间:2018-10-03 05:06:14

标签: c linux

最近一直在使用SIGINT和SIGHUP等信号及其在Linux上正在进行的进程中的作用进行测试。运行以下代码返回了一些有趣的结果。

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

void routine(int p){
    puts("Not finishing");
    sleep(2);
}

main(){
    int i = 0;
    signal(SIGINT, routine);
    signal(SIGHUP, routine);

    while(1){
        printf("%d \n", i++);
    }
}

如您所见,它在无限循环中仅从0开始计数。然后,通过在其创建的进程上使用kill -SIGINT,我得到了以下信息:

Routine

如您所见,在我要求打印例程的那一行之前,程序重复了最后一个数字(而且并非总是如此)。我真的很想知道为什么。

1 个答案:

答案 0 :(得分:1)

您很可能会偶然地避免可怕的错误。

我认为正在发生的情况是信号有时会在printf进行格式化并将字符串格式化为输出缓冲区时中断。然后,信号处理程序中的puts将更多字符串插入输出缓冲区。然后处理程序返回,printf插入换行符并刷新缓冲区。

但是,如果该信号刚好在刷新整个8K输出缓冲区之前发生,将会发生什么。缓冲区位置将在末尾。然后发生puts调用,没有意识到printf已经在刷新和清除缓冲区了。它将puts字符串放在哪里?一开始?在末尾?多余的数据printf是否正在写入过程中,覆盖了puts所添加的字符串?所有这些事情都是可能的。

缓冲的C输出不是可重入的,不能在信号处理程序中使用。