Co powoduje błąd zepsutej rury?

84

Wiem, że wyrzucany jest błąd pękniętej rury, gdy gniazdo po stronie równorzędnej jest zamknięte.

Ale w moim teście zauważyłem, że natychmiastowe wywołanie „wyślij” po tej stronie, gdy strona równorzędna jest zamknięta, nie zawsze prowadzi do błędu zerwanego przewodu.

Na przykład:

Po zamknięciu gniazda po stronie równorzędnej (próbowałem wyczyścić zamknięcie przez wywołanie close, a także nienormalne zamknięcie przez zabicie peera), jeśli spróbuję wysłać 40 bajtów, nie otrzymuję zepsutego potoku, ale jeśli spróbuję wyślij 40000 bajtów, a następnie natychmiast wyświetli błąd zepsutego potoku.

Co dokładnie powoduje pęknięcie rury i czy można przewidzieć jej zachowanie?

Sójka
źródło

Odpowiedzi:

59

Obserwacja zamknięcia sieci może zająć trochę czasu - całkowity czas wynosi nominalnie około 2 minuty (tak, minuty!) Po zamknięciu, zanim wszystkie pakiety przeznaczone dla portu zostaną uznane za martwe. W pewnym momencie został wykryty stan błędu. Po krótkim zapisie jesteś wewnątrz jednostki MTU systemu, więc wiadomość jest umieszczana w kolejce do wysłania. Przy dużym zapisie jesteś większy niż MTU, a system szybciej wykrywa problem. Jeśli zignorujesz sygnał SIGPIPE, funkcje zwrócą błąd EPIPE na zepsutej rurze - w pewnym momencie, gdy zostanie wykryte zerwanie połączenia.

Jonathan Leffler
źródło
4
@varevarao: Nie sądzę, aby kolejkowanie transmisji i wysyłanie w określonych odstępach czasu było obejściem. Kolejkowanie transmisji do momentu, gdy będzie więcej niż MTU do wysłania, może być obejściem, jeśli aplikacja może wytrzymać opóźnienia.
Jonathan Leffler
11

Bieżący stan gniazda jest określany przez aktywność „utrzymywania przy życiu”. W twoim przypadku jest to możliwe, że gdy wykonujesz sendwywołanie, keep-aliveaktywność mówi, że gniazdo jest aktywne, więc sendwywołanie zapisze wymagane dane (40 bajtów) do bufora i zwróci bez błędu.

Kiedy wysyłasz większy fragment, wywołanie send przechodzi w stan blokowania.

Strona podręcznika wysyłania również to potwierdza:

Gdy wiadomość nie mieści się w buforze wysyłania gniazda, funkcja send () normalnie blokuje, chyba że gniazdo zostało ustawione w nieblokującym trybie I / O. W trybie nieblokującym zwróci w tym przypadku EAGAIN

Tak więc, podczas blokowania wolnego dostępnego bufora, jeśli dzwoniący zostanie powiadomiony (przez mechanizm utrzymywania aktywności), że drugi koniec nie jest już obecny, wywołanie wysyłające zakończy się niepowodzeniem.

Przewidywanie dokładnego scenariusza jest trudne przy wspomnianych informacjach, ale uważam, że to powinno być przyczyną twojego problemu.

Vikram.exe
źródło
1
Aktualny stan gniazda jest obserwowany przez aktywność ACK. Keepalive to tylko jedno pomniejsze działanie ACK źródła i jest domyślnie wyłączone.
user207421
3

Może 40 bajtów mieści się w buforze potoku, a 40000 bajtów nie?

Edytować:

Podczas wysyłania wysyłany jest sygnał SIGPIPE, gdy próbujesz pisać do zamkniętego potoku. Nie wiem dokładnie, kiedy sygnał jest wysyłany ani jaki wpływ ma na to bufor potoku. Możesz odzyskać równowagę, przechwytując sygnał za pomocą wywołania sigaction.

Joel
źródło
0

Kiedy peer jest blisko, po prostu nie wiesz, czy po prostu przestaje wysyłać, czy jednocześnie wysyła i odbiera, ponieważ TCP na to pozwala, przy okazji, powinieneś znać różnicę między zamknięciem a zamknięciem. Jeśli peer przestanie wysyłać i odbierać, najpierw wyślesz trochę bajtów, to się powiedzie. Ale jądro równorzędne wyśle ​​Ci RST. Więc później wyślesz kilka bajtów, twoje jądro wyśle ​​ci sygnał SIGPIPE, jeśli złapiesz lub zignorujesz ten sygnał, gdy twoja wysyłka wróci, otrzymasz błąd Broken pipe, lub jeśli nie, domyślne zachowanie twojego programu to awaria .

kingkong
źródło
-1

Wystąpił błąd zerwanej rury po zainstalowaniu nowej sieci. Po upewnieniu się, że port 9100 jest otwarty i może łączyć się z drukarką przez port telnet 9100, zmieniliśmy sterownik drukarki z „HP” na „Generic PDF”, błąd zepsutego przewodu zniknął i mogliśmy drukować pomyślnie.

(RHEL 7, Drukarki były marką Ricoh, konfiguracja HP ​​była już istniejąca i działała w poprzedniej sieci)

Andy T.
źródło