dup(fileno(stdin)),然后产生32个线程 - > I/O错误
我写过Zsh模块。在那里我有一个内置函数映射到Zsh命令。这个函数可以复制其标准输入文件描述符:dup(fileno(stdin)),然后产生32个线程 - > I/O错误
/* Duplicate standard input */
oconf->stream = fdopen(dup(fileno(stdin)), "r");
然后,线程派生,其获得oconf
结构。在该线程,我做的:
errno = 0;
/* Read e.g. 5 characters, putting them after previous portion */
int count = fread(buf + index, 1, read_size, oconf->stream);
/* Ensure that our whole data is a string - null terminated */
buf[ index + count ] = '\0';
if (errno) {
fprintf(oconf->err, "Read error (descriptor: %d): %s\n", fileno(oconf->stream), strerror(errno) >
}
如果我产卵32个线程的zsh:
for ((i=1; i<=32; i ++)); do
ls -R /Users/myuser/Documents | mybuiltin -A myhash_$i $i
done
然后2-3线程都从上面fprintf()
报道的I/O错误,如:
读取错误(描述符:7):输入/输出错误
读取错误(描述符:5)不适当的ioctl用于设备
读取错误(描述:14):用于设备
不适当的ioctl
调试说,这些线程,经过多次(5-20)FREAD()重复,被堵在内核__read_nocancel()
。因此,文件描述符正在变得非常糟糕。
否则这个工程。管道正确传递来自ls -R
的数据,它被定制内建读取。那么危险在哪里? dup()
如何在主线程中执行导致fread()
不可读?我可能会怀疑我是否会在辅助线程中执行dup()
。但我只保留在安全的地方 - 主线程,然后将准备好的流FILE *
流传递到辅助线程。还试用POSIX open()
,read()
和close()
,结果是一样的。
您正在测试errno
错误。如果设置它的函数报告了错误,则只应检查errno
。标准C或POSIX库中的任何函数都不会将errno
设置为零。并且函数可以将errno
设置为非零而不报告错误。
例如,在Solaris上,在写操作之后,如果文件流不是终端(例如,重定向到文件或管道),它就是这种情况(并且可能仍是这种情况)。没有问题;输出设备不是终端,因此终端操作失败,将errno
设置为ENOTTY
。
您目前有:
/* Read e.g. 5 characters, putting them after previous portion */
int count = fread(buf + index, 1, read_size, oconf->stream);
/* Ensure that our whole data is a string - null terminated */
buf[ index + count ] = '\0';
if (errno) {
fprintf(oconf->err, "Read error (descriptor: %d): %s\n", fileno(oconf->stream), strerror(errno));
}
你需要更多的使用类似:
int count = fread(buf + index, 1, read_size, oconf->stream);
if (count == 0)
{
/* EOF or error — this might be a time to use feof() or ferror() */
fprintf(oconf->err, "Read error (descriptor: %d): %s\n", fileno(oconf->stream), strerror(errno));
…flow control?…
}
else
buf[index + count] = '\0';
你可能需要一些其他流的控制信息(退货或折断或设置标志)在EOF和错误路径;从您引用的片段中可能不适用什么是不明确的。