首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >dup( fileno( stdin )),然后生成32个线程-> I/O错误

dup( fileno( stdin )),然后生成32个线程-> I/O错误
EN

Stack Overflow用户
提问于 2017-02-12 14:07:21
回答 1查看 272关注 0票数 0

我写了Zsh模块。在那里,我有一个内置函数映射到Zsh命令。此函数复制它的stdin文件描述符:

代码语言:javascript
复制
/* Duplicate standard input */
oconf->stream = fdopen( dup( fileno( stdin ) ), "r" );

然后生成一个获得oconf结构的线程。在这篇文章中,我做了:

代码语言:javascript
复制
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 ) >
}

如果我在zsh中生成32个线程:

代码语言:javascript
复制
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()上也进行了尝试,结果是相同的。

EN

回答 1

Stack Overflow用户

发布于 2017-02-12 16:25:31

您正在错误地测试errno。只有当设置errno的函数报告错误时,才应该检查它。标准C或POSIX库中没有任何函数将errno设置为零。函数可以将errno设置为非零,而不报告错误。

例如,在Solaris上,在写操作之后,如果文件流不是终端(例如重定向到文件或管道),则为errno == ENOTTY (可能仍然是这样)。没有问题;输出设备不是终端,所以只有终端的操作失败,将errno设置为ENOTTY

你目前有:

代码语言:javascript
复制
/* 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 ));
}

您需要更多地使用以下内容:

代码语言:javascript
复制
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和错误路径中,您可能需要一些其他的控制流细节(返回、中断或设置标志);从引用的片段中不清楚什么是合适的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42188546

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档