2011-11-16 62 views
6

我得到了一些代码打印到标准输出,在伪代码,它看起来像如何检查是否标准输出关闭

int main(){ 
    //allocate data 
    while(conditional){ 
     char *string = makedata(); 
     fprintf(stdout,"%s",string); 
    } 
    //cleanup 
} 

这工作得很好,如果条件被切换到零,但是如果我管输出像

./a.out |head -n10 >dumped 

然后代码从来没有达到清理部分,我不明白如何检查标准输出是否被关闭。

感谢

+0

'feof()'和'ferror()'怎么办? –

回答

5

你的stdout还没有关闭,所以检查这个将是无用的。您的程序已收到SIGPIPE并退出。只要程序写入没有读卡器的管道,SIGPIPE就会被发送。在你的例子中,当head退出时会发生这种情况,关闭它的stdin。

如果您希望程序继续,您应该忽略SIGPIPE。该代码会忽略SIGPIPE:

(void)signal(SIGPIPE, SIG_IGN); 

如果你不想修改你的程序,你可以安排的东西不断从管道读,head关闭其输入后还是一样。

./a.out | (head -n10 >dumped ; cat > /dev/null) 

:外壳例子是有效的bash中,也许不是CSH。

+1

标准输出已关闭。写入已关闭的文件描述符的行为会生成SIGPIPE。 –

+1

@WilliamPursell - 不,管道的另一端*已关闭。写入远端关闭的管道或套接字文件描述符的操作会生成一个SIGPIPE。写入已关闭的文件描述符的操作会生成EBADF。 –

0

我没有尝试过这一点,但你正在使用的标准输出标准的文件描述符提供,您可以尝试执行FSTAT(1 & stat_structure),并检查返回值和错误代码。

3

它通过使用SIGPIPE杀死进程而关闭。

如果你想要去的时候被忽略你的输出,然后设置SIG_IGN处理程序SIGPIPE,并处理来自fprintf错误(将通过缓冲延迟,所以你不能假设已经写入数据实际上已经到达用户)。

1

正如罗布在评论中指出他的回答,你并不担心stdout已经关闭;相反,你担心管道的另一端是关闭的。这可能是家常便饭,但它会导致解决您的问题。也就是说,你不关心stdout是否关闭,但只有当你的printf成功时才会关闭。您应该检查printf的返回值:如果它是-1,则写入失败。

正如西蒙·里克特指出,如果不忽略SIGPIPE,因为写作的结果到标准输出当管道已经被关闭的另一面是,SIG_PIPE将被发送到你将永远不会得到printf函数的返回值该过程。所以你需要做一些事情:

 
    signal(SIGPIPE, SIG_IGN); /* Careful: you now must check the return of *all* writes */ 
    if(fprintf(stdout, ...) == -1) { 
    /* handle the error */ 
    }