2011-11-16 17 views
6

dostałem trochę kodu, który drukuje na standardowe wyjście, w pseudo kod wyglądajak sprawdzić, czy stdout jest zamknięty

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

Działa to dobrze, jeśli warunkowa jest przełączana do zera, ale jeśli rura I wyjście takie jak:

./a.out |head -n10 >dumped 

Następnie kod nigdy nie dociera do części czyszczenia, nie rozumiem, jak sprawdzić, czy standardowe wyjście zostanie zamknięte.

Dzięki

+0

Co z 'feof()' i 'ferror()'? –

Odpowiedz

5

Twoje standardowe wyjście nie zostało zamknięte, więc sprawdzenie tego będzie bezużyteczne. Twój program otrzymał SIGPIPE i zakończył. SIGPIPE jest dostarczany za każdym razem, gdy twój program zapisuje do potoku, na którym nie ma czytelników. W twoim przykładzie zdarza się, gdy head kończy pracę, zamykając jego wejście standardowe.

Powinieneś zignorować SIGPIPE, jeśli chcesz kontynuować program. Kod ten będzie ignorować SIGPIPE:

(void)signal(SIGPIPE, SIG_IGN); 

Jeśli nie chcesz zmodyfikować program, można zorganizować, że coś trwa do zapoznania się z rury, nawet po head zamyka swoje wejście.

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

: przykład powłoki dotyczy bashu może nie csh.

+1

stdout jest zamknięty. Zapisanie do deskryptora pliku, który został zamknięty, generuje SIGPIPE. –

+1

@WilliamPursell - Nie, * inny * koniec rury został zamknięty. Zapisanie do deskryptora pliku potoku lub gniazda, w którym koniec jest zamknięty, generuje SIGPIPE. Zapisanie do deskryptora pliku, który został zamknięty, generuje EBADF. –

0

ja nie próbowałem tego, ale wykonywane były przy użyciu standardowego deskryptor pliku do stdout, może być w stanie spróbować wykonywania fstat (1, & stat_structure) i sprawdzić kody powrotne i błędach .

3

Zamyka się, zabijając proces za pomocą SIGPIPE.

Jeśli chcesz iść, gdy wyjście jest ignorowany, a następnie założyć SIG_IGN obsługi dla SIGPIPE i obsługi błędu z fprintf (które będą opóźnione przez buforowanie, więc nie można zakładać, dane, które zostały napisane faktycznie dotarł do użytkownika).

1

Jak podkreśla Rob w komentarzach do swojej odpowiedzi, nie martwisz się, że standardowe wyjście zostało zamknięte; raczej obawiasz się, że drugi koniec rury jest zamknięty. Może to być pedanteria, ale prowadzi ona do rozwiązania twojego problemu. Mianowicie, nie obchodzi cię, że standardowe wyjście jest zamknięte, ale tylko wtedy, gdy twój printf się powiedzie. Powinieneś sprawdzić wartość zwracaną przez printf: jeśli jest równa -1, to zapis nie powiódł się.

Jako Simon Richter zwraca uwagę, że nigdy nie dostanie wartość zwracaną printf jeśli nie ignorować SIGPIPE, ponieważ wynikiem piśmie do stdout, gdy druga strona rury został zamknięty jest SIG_PIPE zostanie wysłany do proces. Musisz więc zrobić coś takiego:

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