目前,我正在阅读来自execlp的儿童计划的输入行。所以基本上,如果一个子程序无法正常执行,它在读取时不应该是管道信息,并且会抛出错误。
我尝试轮询文件描述符,无论程序是否正确执行,它都返回一个。所以基本上我得到了民意调查,然后fgetc挂起/阻塞,因为没有什么可读,但fgetc也没有返回-1。
阅读和投票:
char* read_line(int fd) {
// fd is a pipe's read end. I know it reads properly.
FILE *file = fdopen(fd, "r");
int ret;
struct pollfd fdinfo[1];
fdinfo[0].fd = fd;
fdinfo[0].events = POLLIN;
ret = poll(fdinfo,1, 1000);
if (ret < 0) {
return "NOPE";
}
char* result = malloc(sizeof(char) * 80);
memset(result, 0, sizeof(int));
int position = 0;
int next = 0;
while (1) {
next = fgetc(file); //STALLING HERE
if (next == '!') {
free(result);
return "!";
}
if (next == EOF || next == '\n') {
result[position] = '\0';
return result;
} else {
result[position++] = (char)next;
}
}
}
答案 0 :(得分:0)
您没有充分检查poll()
提供给您的信息。您确实检测到poll()
通过返回-1报告错误的情况,但它不会保证有任何数据可供读取。否定返回值表示poll()
未能完成其工作;它没有告诉你任何轮询文件描述符的状态。
首先,poll()
如果超时则返回0。在这种情况下,您的代码只是向前滚动并尝试从文件描述符中读取,除非数据恰好在poll()
的返回和fgetc()
的调用之间到达,否则将阻止该文件描述符。
在第二位,poll()
通过设置一个或多个相应的revent
位并在该FD上报告事件(部分通过返回正数)来指示指定文件描述符的问题)。具体地,
如果条件为真,
poll()
会在revents中设置POLLHUP,POLLERR和POLLNVAL标志, 即使应用程序未在事件中设置相应的位
和
正[返回]值表示
pollfd
成员非零的revents
个结构[...]的总数
(POSIX 1003.1-2008;重点补充)
如果写入管道另一端的子进程崩溃,您可能会看到POLLHUP事件。如果您的程序以某种方式搞砸了文件描述符处理,您可能会看到POLLNVAL事件,并且您始终必须考虑到I / O错误的可能性,poll()
发出POLLERR事件的信号。
因此,为避免阻塞,只有当poll()
返回1并且在文件中的事件中发出POLLIN信号时,才应尝试从管道读取。可以想象,您可能会看到POLLERR或POLLHUP。如果有任何POLLERR,我建议中止,但是当管道的写入端在任何进程中不再打开时,可以预期POLLHUP,并且这不会使任何可能仍然可用的数据无效(这将是由陪同的POLLIN发出信号。