Was verursacht den Fehler "Broken Pipe"?

83

Ich weiß, dass ein Rohrbruchfehler ausgelöst wird, wenn der Sockel auf der Peer-Seite geschlossen wird.

In meinem Test habe ich jedoch festgestellt, dass ein sofortiger Sendeanruf auf dieser Seite, wenn die Peer-Seite geschlossen ist, nicht immer zu einem Rohrbruchfehler führt.

Z.B:

Wenn ich nach dem Schließen des Sockets auf der Peer-Seite (ich habe versucht, das Schließen sauber zu machen, indem ich close aufrufe, und auch das abnormale Schließen, indem ich den Peer töte) versuche, 40 Bytes zu senden, bekomme ich keine kaputte Pipe, aber wenn ich es versuche Senden Sie 40000 Bytes, dann gibt es sofort einen Rohrbruchfehler.

Was genau verursacht Rohrbruch und kann das Verhalten vorhergesagt werden?

Jay
quelle

Antworten:

59

Es kann einige Zeit dauern, bis das Netzwerk in der Nähe beobachtet wird. Die Gesamtzeit beträgt nominell etwa 2 Minuten (ja, Minuten!) Nach einem Abschluss, bevor angenommen wird, dass alle für den Port bestimmten Pakete tot sind. Der Fehlerzustand wird irgendwann erkannt. Mit einem kleinen Schreibvorgang befinden Sie sich in der MTU des Systems, sodass die Nachricht zum Senden in die Warteschlange gestellt wird. Mit einem großen Schreibvorgang sind Sie größer als die MTU und das System erkennt das Problem schneller. Wenn Sie das SIGPIPE-Signal ignorieren, geben die Funktionen einen EPIPE-Fehler bei einem Rohrbruch zurück - irgendwann, wenn die Unterbrechung der Verbindung erkannt wird.

Jonathan Leffler
quelle
4
@varevarao: Ich denke nicht, dass das Einreihen von Übertragungen und das Senden in bestimmten Intervallen eine Problemumgehung ist. Das Einreihen von Übertragungen in die Warteschlange, bis mehr als die MTU gesendet werden muss, kann eine Problemumgehung sein, wenn Ihre Anwendung mit den Verzögerungen leben kann.
Jonathan Leffler
11

Der aktuelle Status eines Sockets wird durch die Aktivität "Keep-Alive" bestimmt. In Ihrem Fall ist es möglich, dass senddie keep-aliveAktivität beim Ausgeben des Anrufs anzeigt, dass der Socket aktiv ist, und dass der sendAnruf die erforderlichen Daten (40 Byte) in den Puffer schreibt und ohne Fehler zurückgibt.

Wenn Sie einen größeren Block senden, wird der Sendeanruf blockiert.

Die Send Manpage bestätigt dies auch:

Wenn die Nachricht nicht in den Sendepuffer des Sockets passt, blockiert send () normalerweise, es sei denn, der Socket wurde in den nicht blockierenden E / A-Modus versetzt. Im nicht blockierenden Modus würde in diesem Fall EAGAIN zurückgegeben

Wenn der Anrufer beim Blockieren des frei verfügbaren Puffers benachrichtigt wird (durch einen Keep-Alive-Mechanismus), dass das andere Ende nicht mehr vorhanden ist, schlägt der Sendeanruf fehl.

Die Vorhersage des genauen Szenarios ist mit den genannten Informationen schwierig, aber ich glaube, dies sollte der Grund für Ihr Problem sein.

Vikram.exe
quelle
1
Der aktuelle Status des Sockets wird durch die ACK-Aktivität beobachtet. Keepalive ist nur eine untergeordnete ACK-Quellaktivität und standardmäßig deaktiviert.
Marquis von Lorne
3

Vielleicht passen die 40 Bytes in den Pipe-Puffer und die 40000 Bytes nicht?

Bearbeiten:

Der Sendevorgang erhält ein SIGPIPE-Signal, wenn Sie versuchen, in eine geschlossene Pipe zu schreiben. Ich weiß nicht genau, wann das Signal gesendet wird oder wie sich der Pipe-Puffer darauf auswirkt. Möglicherweise können Sie sich erholen, indem Sie das Signal mit dem Sigaction-Aufruf abfangen.

Joel
quelle
0

Wenn Peer geschlossen wird, wissen Sie einfach nicht, ob das Senden oder das Senden und Empfangen beendet wird. Da TCP dies zulässt, sollten Sie übrigens den Unterschied zwischen Schließen und Herunterfahren kennen. Wenn der Peer das Senden und Empfangen beendet, senden Sie zuerst einige Bytes. Dies ist erfolgreich. Der Peer-Kernel sendet Ihnen jedoch RST. Wenn Sie anschließend einige Bytes senden, sendet Ihr Kernel Ihnen das SIGPIPE-Signal. Wenn Sie dieses Signal abfangen oder ignorieren, wenn Ihr Sendevorgang zurückkehrt, erhalten Sie nur einen Fehler "Broken Pipe" oder wenn dies nicht der Fall ist, stürzt das Standardverhalten Ihres Programms ab .

Kingkong
quelle
-1

Wir hatten den Fehler "Broken Pipe", nachdem ein neues Netzwerk eingerichtet wurde. Nachdem sichergestellt wurde, dass Port 9100 geöffnet war und über Telnet-Port 9100 eine Verbindung zum Drucker hergestellt werden konnte, haben wir den Druckertreiber von "HP" in "Generisches PDF" geändert. Der Fehler "Rohrbruch" wurde behoben und konnte erfolgreich gedruckt werden.

(RHEL 7, Drucker der Marke Ricoh, die HP-Konfiguration war im vorherigen Netzwerk bereits vorhanden und funktionsfähig)

Andy T.
quelle