C语言中poll()无法检测jq输出作为stdin的问题咨询
为什么
poll()无法识别jq输出作为程序的标准输入? 问题场景
我编写了一个C语言函数,使用poll()检测标准输入是否存在可读数据,代码如下:
#include <stdio.h> #include <sys/poll.h> // 其他代码 void check_stdin(){ struct pollfd fds; int ret; fds.fd = 0; fds.events = POLLIN; ret = poll(&fds, 1, 10); printf("Return value: %d\n", ret); if(ret != 1){ printf("stdin could not be read\n"); } }
其中fds.fd=0对应STDIN的文件描述符,fds.events=POLLIN用于检测可读事件,超时时间设置为10毫秒。
执行以下命令:
echo "{\"key\": 1}" | jq .key | ./test_stdin
得到输出:
Return value: 0 stdin could not be read
按预期,当stdin存在可读数据时poll()的返回值应为1,为何jq的标准输出无法被./test_stdin识别为标准输入?
问题根源
核心原因是超时时间设置过短。poll()仅等待10毫秒,而管道上游的jq进程需要完成启动、JSON解析、结果输出这些操作,耗时通常会超过10毫秒。当你的程序调用poll()时,jq还未将数据写入管道,此时标准输入对应的管道读端没有可读数据,poll()就会因超时返回0。
管道是基于缓冲区的通信机制,只有上游进程将数据写入管道缓冲区后,下游进程的poll()才能检测到POLLIN可读事件。10毫秒的等待窗口完全不足以覆盖jq的处理周期。
解决办法
- 延长单次超时时间:将
poll()的超时参数调整为更大的值,比如1000毫秒(1秒),给上游进程足够的时间输出数据:ret = poll(&fds, 1, 1000); - 循环轮询检测:如果需要更灵活的等待逻辑,可以循环调用
poll(),直到检测到数据或达到总超时时间:int total_wait_ms = 5000; // 总等待5秒 int interval_ms = 100; // 每次检测间隔100毫秒 int ret = 0; struct pollfd fds = {.fd = 0, .events = POLLIN}; while (total_wait_ms > 0 && ret == 0) { ret = poll(&fds, 1, interval_ms); total_wait_ms -= interval_ms; } - 增加错误处理:不要忽略
poll()返回-1的情况(系统调用失败),补充错误判断:if (ret == -1) { perror("poll failed"); return; }
内容的提问来源于stack exchange,提问作者sriganesh
相关产品推荐
相关产品推荐

