2011-11-16 26 views
6

Tôi có một số mã mà in đến stdout, trong mã giả có vẻ nhưlàm thế nào để kiểm tra xem một stdout được đóng

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

này hoạt động tốt, nếu có điều kiện được bật lên thành không, nhưng nếu tôi đường ống đầu ra như

./a.out |head -n10 >dumped 

Sau đó, mã không bao giờ đạt đến phần dọn dẹp, tôi không hiểu cách kiểm tra xem giá trị có được đóng hay không.

Cảm ơn

+0

Còn 'feof()' và 'ferror()' thì sao? –

Trả lời

5

Điểm xuất phát của bạn chưa được đóng, vì vậy việc kiểm tra điều đó sẽ vô dụng. Chương trình của bạn đã nhận được SIGPIPE và đã thoát. Một SIGPIPE được phân phối bất cứ khi nào chương trình của bạn ghi vào một đường ống mà trên đó không có độc giả. Trong ví dụ của bạn, điều đó xảy ra khi các lần thoát head, đóng stdin của nó.

Bạn nên bỏ qua SIGPIPE nếu bạn muốn chương trình của mình tiếp tục. Mã này sẽ bỏ qua SIGPIPE:

(void)signal(SIGPIPE, SIG_IGN); 

Nếu bạn không muốn thay đổi chương trình của bạn, bạn có thể sắp xếp một cái gì đó tiếp tục đọc từ đường ống, ngay cả sau khi head đóng đầu vào của nó.

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

: Ví dụ vỏ có giá trị trong bash, có lẽ không phải cho csh.

+1

stdout bị đóng. Hành vi ghi vào bộ mô tả tập tin đã bị đóng sẽ tạo ra SIGPIPE. –

+1

@WilliamPursell - Không, đầu * khác của ống đã bị đóng. Hành vi ghi vào bộ mô tả tệp ống hoặc ổ cắm trong đó phần cuối được đóng sẽ tạo ra SIGPIPE. Hành vi ghi vào tập tin mô tả đã bị đóng tạo EBADF. –

0

Tôi đã không cố gắng này, nhưng miễn là bạn đang sử dụng bộ mô tả tập tin tiêu chuẩn cho thiết bị xuất chuẩn, bạn có thể cố gắng thực hiện một fstat (1, & stat_structure) và kiểm tra mã trở lại và không bị lỗi .

3

Đóng cửa bằng cách hủy quá trình với SIGPIPE.

Nếu bạn muốn tiếp tục khi đầu ra của bạn bị bỏ qua, sau đó thiết lập trình xử lý SIG_IGN cho SIGPIPE và xử lý lỗi từ fprintf (sẽ bị trì hoãn do bị giật, vì vậy bạn không thể giả định dữ liệu đã được ghi đã thực sự tiếp cận người dùng).

1

Vì Rob chỉ ra trong các nhận xét cho câu trả lời của anh ấy, bạn không lo lắng rằng stdout đã bị đóng; thay vào đó, bạn đang lo lắng rằng đầu kia của ống được đóng lại. Điều này có thể là hành lang, nhưng nó dẫn đến giải pháp cho vấn đề của bạn. Cụ thể, bạn không quan tâm nếu stdout được đóng lại, nhưng chỉ khi printf của bạn thành công. Bạn nên kiểm tra giá trị trả về của printf: nếu nó là -1, thì ghi đã thất bại.

Như Simon Richter chỉ ra, bạn sẽ không bao giờ nhận được giá trị trả về của printf nếu bạn không bỏ qua SIGPIPE, bởi vì kết quả của việc viết thành stdout khi phía bên kia của đường ống đã bị đóng là SIG_PIPE sẽ được gửi đến quá trình. Vì vậy, bạn cần phải làm điều gì đó như:

 
    signal(SIGPIPE, SIG_IGN); /* Careful: you now must check the return of *all* writes */ 
    if(fprintf(stdout, ...) == -1) { 
    /* handle the error */ 
    } 
Các vấn đề liên quan