web-dev-qa-db-de.com

Was verursacht den Rohrbruchfehler?

Ich weiß, dass ein Rohrbruchfehler ausgelöst wird, wenn die Buchse auf der Gegenseite geschlossen ist.

In meinem Test habe ich jedoch festgestellt, dass ein sofortiger "Send" -Aufruf auf dieser Seite, wenn die Peerseite geschlossen ist, nicht immer zu einem Pipe-Fehler führt.

Z.B.:

Wenn ich nach dem Schließen des Sockets auf der Peerseite (ich habe versucht, durch Aufrufen von close sauber zu schließen, und auch durch Beenden des Peers abnormal zu schließen) versuche ich, 40 Bytes zu senden, bekomme ich keine kaputte Pipe, aber wenn ich es versuche Sende 40000 Bytes, dann gibt es sofort einen Pipe-Fehler.

Was genau verursacht einen Rohrbruch und kann sein Verhalten vorhergesagt werden?

70
Jay

Es kann einige Zeit dauern, bis das Netzwerk in der Nähe ist - die Gesamtzeit beträgt nominal etwa 2 Minuten (ja, Minuten!) Nach dem Schließen, bevor angenommen wird, dass alle für den Port bestimmten Pakete tot sind. Der Fehlerzustand wird irgendwann erkannt. Mit einem kleinen Schreibzugriff befinden Sie sich in der MTU des Systems, sodass die Nachricht zum Senden in die Warteschlange gestellt wird. Mit einem großen Schreibzugriff 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 für eine unterbrochene Leitung zurück - irgendwann, wenn die Unterbrechung der Verbindung erkannt wird.

47

Der aktuelle Status eines Sockets wird durch die Aktivität "Keep-Alive" bestimmt. In Ihrem Fall ist es möglich, dass bei der Ausgabe des send -Aufrufs der keep-alive activity gibt an, dass der Socket aktiv ist, und der Aufruf send schreibt die erforderlichen Daten (40 Byte) in den Puffer und gibt sie ohne Fehler zurück.

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

Die send man page bestätigt dies ebenfalls:

Wenn die Nachricht nicht in den Sendepuffer des Sockets passt, wird send () normalerweise blockiert, 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 (durch den Keep-Alive-Mechanismus) benachrichtigt wird, dass das andere Ende nicht mehr vorhanden ist, schlägt der Sendeanruf fehl, während er für den frei verfügbaren Puffer blockiert.

Das genaue Szenario vorherzusagen ist mit den genannten Informationen schwierig, aber ich glaube, dies sollte der Grund für Ihr Problem sein.

8
Vikram.exe

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

Bearbeiten:

Der Sendeprozess 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 Buffer darauf auswirkt. Sie können sich möglicherweise erholen, indem Sie das Signal mit dem Sigaktionsaufruf abfangen.

3
Joel

Wenn Peer-Close ausgeführt wird, wissen Sie nicht, ob das Senden oder das Senden und Empfangen beendet wird. Wenn TCP dies zulässt, sollten Sie übrigens den Unterschied zwischen Close und Shutdown kennen. Wenn der Peer aufhört zu senden und zu empfangen, senden Sie zuerst einige Bytes. Dies ist erfolgreich. Der Peer-Kernel sendet Ihnen jedoch RST. Wenn Sie also später einige Bytes senden, sendet Ihr Kernel das SIGPIPE-Signal, wenn Sie dieses Signal abfangen oder ignorieren, wenn Ihr Send zurückkehrt, erhalten Sie nur einen Pipe-Fehler, oder wenn Sie dies nicht tun, stürzt das Standardverhalten Ihres Programms ab .

0
kingkong