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

标签 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

如您所见,在我请求例程打印的那一行之前,程序重复了最后一个数字(这种情况并不总是发生)。我真的很想知道为什么。

最佳答案

您很可能是偶然地勉强避免了可怕的错误。

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

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

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

关于c - 在 linux 上测试 SIGINT 和 SIGHUP 时有趣的类似故障的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52620016/

相关文章:

java - 如何在授权 Java 程序写入 Web 服务器文件夹时保护它

linux - Docker Busybox 容器添加组和用户

c - 在 Cyrus SASL 中使用外部机制

c - 如何在不使用 extern 关键字的情况下访问全局值?

c - 在内核模块中,如何知道给定路径是文件还是目录?

c++ - 如何使用 Linux getrandom 系统调用生成一个范围内的随机数?

java - if 语句的复杂性

c - 实现我自己的系统调用

c - 代码中有什么错误?

IZPack 5.0.0 处理阶段的 linux 命令 mkdir、rm -r 和 ln -s -T