You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

poll()调用返回未被手册记载的ECHILD错误,求原因分析

poll()返回未记载的ECHILD错误的排查思路

核心原因:信号处理干扰导致errno被覆盖

ECHILD(错误码10)的常规含义是"没有子进程",但poll()本身不会直接返回这个错误。最常见的触发场景是:

  • 程序注册了SIGCHLD信号处理函数用于回收退出的子进程;
  • poll()等待过程中,子进程退出触发SIGCHLD,导致poll()被中断(原本应返回-1且errno=EINTR);
  • 信号处理函数中调用了wait()/waitpid(),若此时没有待回收的子进程(比如信号被多次触发、子进程已被回收),waitpid()会将errno设置为ECHILD;
  • 当你在poll()返回-1后读取errno时,拿到的是信号处理函数修改后的ECHILD,而非poll()本身设置的EINTR。

验证与解决方法

  1. 检查信号处理逻辑
    查看代码中是否存在未正确处理返回值的SIGCHLD处理函数,比如:

    void sigchld_handler(int sig) {
        // 未检查返回值的waitpid调用会修改errno
        waitpid(-1, NULL, WNOHANG);
    }
    

    这类代码在无可用子进程回收时,waitpid()返回-1并将errno设为ECHILD。

  2. 修复信号处理函数
    在信号处理函数中保存和恢复errno,避免干扰主逻辑:

    void sigchld_handler(int sig) {
        int saved_errno = errno;
        // 循环回收所有退出的子进程,避免信号丢失
        while (waitpid(-1, NULL, WNOHANG) > 0);
        errno = saved_errno;
    }
    
  3. 处理poll的EINTR情况
    即使修复了信号处理函数,poll()仍可能被信号中断,需在主逻辑中处理该情况而非直接退出:

    else if(rc < 0) {
        if (errno == EINTR) {
            // 被信号中断,继续等待
            continue;
        }
        printf("poll error %d\n", errno);
        exit(1);
    }
    

其他边缘可能性

如果监听的fd是与子进程关联的管道、PTY等描述符,某些特定内核版本或系统中,可能在子进程异常退出时出现这类未文档化的poll()行为,但这种情况远不如信号处理干扰常见,优先排查信号逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:05:54