Co sprawia, że ​​proces uniksowy umiera z Broken pipe?

30

Oto kilka opcji, o których myślałem, ale nie jestem pewien, która z nich jest właściwa.

  1. Wystąpił błąd we / wy podczas odczytu z potoku.
  2. Proces zapisu na drugim końcu potoku umarł z powodu awarii.
  3. Wszystkie procesy, które mogły pisać do potoku, zamknęły go.
  4. Bufor zapisu potoku jest pełny.
  5. Element równorzędny zamknął drugi kierunek rury dupleksowej.
  6. Zapis nie powiódł się, ponieważ nie ma procesów, które mogłyby odczytać z potoku.
  7. Wywołanie systemowe zwróciło błąd EPIPE i nie zainstalowano programu obsługi błędów.
siamii
źródło
Jakie jest Twoje pytanie? Czy pytasz, który z nich jest poprawny, czy też są jakieś inne rzeczy, które mogą spowodować pęknięcie rury?
EightBitTony
@EightBitTony Które z nich są poprawne
siamii

Odpowiedzi:

38

Proces otrzymuje SIGPIPE, gdy próbuje zapisać do potoku (nazwanego lub nie) lub gniazda typu SOCK_STREAM, w którym nie ma już czytnika.

To ogólnie pożądane zachowanie. Typowym przykładem jest:

find . | head -n 1

Nie chcesz findkontynuować działania po headzakończeniu (a następnie zamknięciu jedynego deskryptora pliku otwartego do odczytu na tym potoku).

yesKomenda zazwyczaj polega na tym sygnałem do zakończenia.

yes | some-command

Napiszę „y”, dopóki jakieś polecenie się nie zakończy.

Zauważ, że to nie tylko po wyjściu komend, ale także wtedy, gdy wszyscy czytelnicy zamknęli czytanie fd do potoku. W:

yes | ( sleep 1; exec <&-; ps -fC yes)
      1 2       1        0

Będzie 1 (podpowłoka), następnie 2 (podpowłoka + uśpienie), następnie 1 (podpowłoka), a następnie 0 odczytanie fd z potoku po tym, jak podpowłoka wyraźnie zamknie swoje standardowe wejście, i wtedy yesotrzyma SIGPIPE.

Powyżej, większość powłok użyć pipe(2)podczas ksh93używa socketpair(2), ale zachowanie jest taka sama w tym względzie.

Gdy proces ignoruje SIGPIPE, wywołanie systemowe piśmie (ogólnie write, ale może być pwrite, send, splice...) wraca z EPIPEbłędem. Tak więc procesy, które chcą ręcznie obsługiwać uszkodzoną rurę, zwykle ignorują SIGPIPE i podejmują działania po błędzie EPIPE.

Stéphane Chazelas
źródło
14

(6)

Zapis nie powiódł się, ponieważ nie ma procesów, które mogłyby odczytać z potoku.

Chociaż, chyba że powielisz deskryptory i rozwidlenie, na początku może być tylko jeden proces: ogólnie potok ma jeden czytnik i jeden program piszący, a gdy jeden z nich zamyka połączenie, potok jest nieczynny. Jeśli używasz nazwanego potoku, możesz z nim wykonywać wiele połączeń (szeregowo), ale każde z nich reprezentuje nowy potok w tym sensie. Zatem „potok” do wątku lub procesu jest synonimem deskryptora pliku.

Od man 7 pipe:

Jeśli wszystkie deskryptory plików odnoszące się do końca odczytu potoku zostaną zamknięte, wówczas write (2) spowoduje wygenerowanie sygnału SIGPIPE dla procesu wywołującego. Jeśli proces wywołujący ignoruje ten sygnał, wówczas zapis (2) kończy się niepowodzeniem z błędem EPIPE.

„Złamana rura” jest więc dla pisarza tym, czym EOF jest dla czytelnika.

Złotowłosa
źródło
0

Przerwana rura zdarza się, gdy proces odczytu kończy się przed procesem zapisu. Więc poszedłbym z (6)

SidJ
źródło
2
Może istnieć kilka procesów odczytu lub zapisu na potoku, a tym samym procesem może być odczyt i zapis. Nie chodzi też o wyjście, chodzi o zamknięcie deskryptora pliku.
Stéphane Chazelas