Was bringt einen Unix-Prozess dazu, mit Broken Pipe zu sterben?

30

Hier sind einige Optionen, die ich mir überlegt habe. Ich bin mir nicht sicher, welche die richtige ist.

  1. In der Pipe ist ein E / A-Fehler aufgetreten.
  2. Das Schreiben auf das andere Ende der Pipe ist fehlgeschlagen.
  3. Alle Prozesse, die in die Pipe schreiben konnten, haben sie geschlossen.
  4. Der Schreibpuffer der Pipe ist voll.
  5. Der Peer hat die andere Richtung des Duplex-Pipes geschlossen.
  6. Das Schreiben ist fehlgeschlagen, weil es keine Prozesse gibt, die von der Pipe lesen könnten.
  7. Ein Systemaufruf hat den EPIPE-Fehler zurückgegeben, und es wurde kein Fehlerbehandlungsprogramm installiert.
siamii
quelle
Was ist deine Frage? Fragen Sie sich, welche davon richtig ist, oder ob es andere Dinge gibt, die zu einem Rohrbruch führen können?
EightBitTony
@EightBitTony Welche davon ist richtig
siamii

Antworten:

38

Ein Prozess empfängt ein SIGPIPE, wenn er versucht, in eine Pipe (mit oder ohne Namen) oder einen Socket vom Typ SOCK_STREAM zu schreiben, für die kein Leser mehr vorhanden ist.

Es ist im Allgemeinen gewolltes Verhalten. Ein typisches Beispiel ist:

find . | head -n 1

Sie möchten nicht findweiterlaufen, wenn headdas Programm beendet wurde (und dann den einzigen Dateideskriptor geschlossen hat, der zum Lesen in dieser Pipe geöffnet ist).

Der yesBefehl verlässt sich normalerweise auf dieses Signal, um zu beenden.

yes | some-command

Schreibt "y", bis ein Befehl beendet wird.

Beachten Sie, dass dies nicht nur beim Beenden von Befehlen der Fall ist, sondern auch, wenn alle Leser ihre Lese-FD für die Pipe geschlossen haben. Im:

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

Es wird 1 (die Subshell) geben, dann 2 (Subshell + Sleep), dann 1 (Subshell) und dann 0 fd, die aus der Pipe gelesen werden, nachdem die Subshell ihre Standard-ID explizit geschlossen yeshat. Dann wird eine SIGPIPE empfangen.

Oben verwenden die meisten Shells eine pipe(2)Weile ksh93a socketpair(2), aber in dieser Hinsicht ist das Verhalten dasselbe.

Wenn ein Prozess die SIGPIPE ignoriert, rufen Sie das Schreibsystem ( in der Regel write, könnte aber sein pwrite, send, splice...) kehrt mit einem EPIPEFehler. Daher ignorieren Prozesse, die die unterbrochene Leitung manuell behandeln möchten, normalerweise SIGPIPE und ergreifen Maßnahmen bei einem EPIPE-Fehler.

Stéphane Chazelas
quelle
14

(6)

Das Schreiben ist fehlgeschlagen, weil es keine Prozesse gibt, die von der Pipe lesen könnten.

Wenn Sie Deskriptoren und Fork nicht duplizieren, kann es am Anfang nur einen Prozess geben: Im Allgemeinen verfügt eine Pipe über einen Reader und einen Writer. Wenn einer von ihnen die Verbindung schließt, ist die Pipe nicht mehr funktionsfähig. Wenn Sie eine Named Pipe verwenden, können Sie mehrere (serielle) Verbindungen damit herstellen, aber jede repräsentiert in diesem Sinne eine neue Pipe. Eine "Pipe" zu einem Thread oder Prozess ist also gleichbedeutend mit einem Dateideskriptor.

Von man 7 pipe:

Wenn alle Dateideskriptoren, die sich auf das Leseende einer Pipe beziehen, geschlossen wurden, wird durch Schreiben (2) ein SIGPIPE-Signal für den aufrufenden Prozess generiert. Wenn der aufrufende Prozess dieses Signal ignoriert, schlägt Schreiben (2) mit dem Fehler EPIPE fehl.

Eine "kaputte Pfeife" ist für den Schreiber das, was EOF für den Leser ist.

Goldlöckchen
quelle
0

Eine unterbrochene Pipe tritt auf, wenn der Lesevorgang vor dem Schreibvorgang beendet wird. Also würde ich gehen mit (6)

SidJ
quelle
2
Es können mehrere Prozesse zum Lesen oder Schreiben einer Pipe vorhanden sein, und der gleiche Prozess kann zum Lesen und Schreiben verwendet werden. Es geht auch nicht darum zu beenden, sondern den Dateideskriptor zu schließen.
Stéphane Chazelas