2011-11-16 59 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 */ 
    }