C程序中收到SIGCHLD信号后getline停止工作的原因是什么?
问题根因
你遇到的无限循环问题由两个核心编码错误共同导致:
- sigaction结构体未正确初始化,未配置SA_RESTART标志
你定义struct sigaction sa后仅赋值了sa_handler字段,剩余的sa_flags、sa_mask等字段都是栈上的随机垃圾值,属于未定义行为。更关键的是你没有主动设置SA_RESTART标志:当阻塞的read系统调用(getline底层调用该接口)被SIGCHLD信号中断时,默认会直接返回EINTR错误,不会自动重启读取操作。 - 未判断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
相关产品推荐
相关产品推荐

