You need to enable JavaScript to run this app. C程序中收到SIGCHLD信号后getline停止工作的原因是什么?
优惠活动
大模型
产品
解决方案
定价
更多

C程序中收到SIGCHLD信号后getline停止工作的原因是什么?

问题根因

你遇到的无限循环问题由两个核心编码错误共同导致:

  1. sigaction结构体未正确初始化,未配置SA_RESTART标志
    你定义struct sigaction sa后仅赋值了sa_handler字段,剩余的sa_flags、sa_mask等字段都是栈上的随机垃圾值,属于未定义行为。更关键的是你没有主动设置SA_RESTART标志:当阻塞的read系统调用(getline底层调用该接口)被SIGCHLD信号中断时,默认会直接返回EINTR错误,不会自动重启读取操作。
  2. 未判断getline的返回值,未处理系统调用中断错误
    getline在底层read被信号中断时会返回-1,同时设置errno为EINTR。你的代码完全没有检查该返回值,也没有清除标准输入流的错误标记,下一次循环调用getline时,会直接检测到流处于错误状态,立刻返回失败,根本不会等待用户输入,因此程序进入无限打印counter的死循环。

修复方案

你可以任选以下一种方案修复问题:

方案1:配置信号处理自动重启系统调用

在注册SIGCHLD信号处理函数前,完整初始化sigaction结构体并添加SA_RESTART标志,被信号中断的慢系统调用会自动重启,getline会继续等待用户输入:

// 注册信号前先清空整个结构体,避免垃圾值
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler;
// 添加SA_RESTART标志,自动重启被中断的系统调用
sa.sa_flags = SA_RESTART;
sigaction(SIGCHLD, &sa, NULL);

方案2:显式处理getline的中断错误

如果你不想开启自动重启逻辑,可以在调用getline后判断返回值,遇到EINTR错误时清除流错误标记并重试:

printf("counter=%d\n",counter);
ssize_t ret = getline(&input,&size,stdin);
if (ret == -1) {
    if (errno == EINTR) {
        // 信号中断,清除流错误标记,跳过本次逻辑进入下一轮循环
        clearerr(stdin);
        continue;
    }
    // 其他错误,按需处理
    break;
}

内容的提问来源于stack exchange,提问作者Martian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.21 07:54:07