最近一直在测试使用 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,我得到了以下信息:
如您所见,在我请求例程打印的那一行之前,程序重复了最后一个数字(这种情况并不总是发生)。我真的很想知道为什么。
最佳答案
您很可能是偶然地勉强避免了可怕的错误。
我认为正在发生的事情是,当 printf
正在将字符串格式化到输出缓冲区时,信号有时会中断。然后信号处理程序中的 puts
将更多字符串插入输出缓冲区。然后处理程序返回,printf
插入换行符并刷新缓冲区。
但是猜猜如果这个信号发生在一个完整的 8K 输出缓冲区刷新之前会发生什么。缓冲位置将在最后。然后发生 puts
调用,没有意识到 printf
已经在刷新和清除缓冲区的过程中。它会将 puts
字符串放在哪里?一开始?在最后?多余的数据 printf
是否正在写入 puts
添加的字符串?所有这些都是可能的。
缓冲的 C 输出不可重入,不能用于信号处理程序。
关于c - 在 linux 上测试 SIGINT 和 SIGHUP 时有趣的类似故障的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52620016/