我得到了一些打印到stdout的代码,伪代码看起来像是
int main(){
//allocate data
while(conditional){
char *string = makedata();
fprintf(stdout,"%s",string);
}
//cleanup
}
如果将条件切换为零,这可以正常工作,但如果我像
那样管道输出./a.out |head -n10 >dumped
然后代码永远不会到达清理部分,我不明白如何检查stdout是否关闭。
由于
答案 0 :(得分:5)
您的标准输出尚未关闭,因此检查该标准将毫无用处。您的计划已收到SIGPIPE并退出。只要您的程序写入没有读取器的管道,就会提供SIGPIPE。在您的示例中,当head
退出,关闭其标准输入时会发生这种情况。
如果您希望程序继续,则应忽略SIGPIPE。此代码将忽略SIGPIPE:
(void)signal(SIGPIPE, SIG_IGN);
如果您不想修改程序,即使head
关闭其输入,您也可以安排从管道继续读取内容。 1
./a.out | ( head -n10 >dumped ; cat > /dev/null )
1 :shell示例对bash有效,可能不适用于csh。
答案 1 :(得分:3)
通过使用SIGPIPE
终止进程来关闭它。
如果您希望在忽略输出时继续,请为SIG_IGN
设置SIGPIPE
处理程序,并处理来自fprintf
的错误(将被延迟缓冲,因此您不能假设已写入的数据实际已到达用户。)
答案 2 :(得分:1)
正如Rob在评论中指出的那样,你并不担心stdout已被关闭;相反,你担心管道的另一端是关闭的。这可能是迂腐,但它可以解决您的问题。也就是说,你不关心stdout是否关闭,但只有你的printf成功。你应该检查printf的返回值:如果是-1,则写入失败。
正如Simon Richter指出的那样,如果你不忽略SIGPIPE,你永远不会得到printf的返回值,因为当管道的另一边被关闭时写入stdout的结果是SIG_PIPE将被发送到处理。所以你需要做一些事情:
signal( SIGPIPE, SIG_IGN ); /* Careful: you now must check the return of *all* writes */ if( fprintf( stdout, ... ) == -1 ) { /* handle the error */ }
答案 3 :(得分:0)
我没试过这个,但如果您使用stdout的标准文件描述符,您可以尝试执行fstat(1,& stat_structure)并检查返回和错误代码。