2010-02-10 12 views
5

Mam aplikację, która składa się z dwóch procesów (nazwijmy je A i B), połączonych ze sobą za pośrednictwem gniazd domeny Unix. W większości przypadków działa to dobrze, ale niektórzy użytkownicy zgłaszają następujące zachowanie:Co może spowodować spontaniczny błąd EPIPE bez wywołania end() lub awarii?

  1. A wysyła żądanie do B. To działa. A zaczyna czytać odpowiedź od B.
  2. B wysyła odpowiedź do A. Odpowiednie wywołanie write() zwraca błąd EPIPE, w wyniku czego B zamyka() gniazdo. Jednak A zrobił nie close() gniazda, ani się nie zawiesił.
  3. A's read() wywołanie zwraca 0, wskazując koniec pliku. A uważa, że ​​B przedwcześnie zamknęło połączenie.

użytkowników zgłaszało również odmiany tego zachowania, np:

  1. A wysyła żądanie do B. To działa częściowo, ale przed całą żądanie jest wysyłane Napisz na() wywołanie zwraca EPIPE i w wyniku A close() gniazdo. Jednak B nie zamknął() gniazda, ani się nie zawiesił.
  2. B odczytuje częściową prośbę, a następnie nagle otrzymuje EOF.

Problem polega na tym, że nie mogę w ogóle odtworzyć tego zachowania lokalnie. Próbowałem już OS X i Linuxa. Użytkownicy są na różnych systemach, głównie OS X i Linux.

Rzeczy, które ja już wypróbowane i uznane:

  • Pokój Close() błędy (zamknij() jest wywoływana dwa razy tego samego deskryptora pliku): chyba nie tak, że powodować błędy EBADF, ale Nie widziałem ich.
  • Zwiększenie maksymalnego limitu deskryptora pliku. Jeden z użytkowników zgłosił, że to zadziałało dla niego, reszta zgłosiła, że ​​tak nie jest.

Co jeszcze może spowodować takie zachowanie? Wiem na pewno, że ani A, ani B nie zamkną() gniazda przedwcześnie, i wiem na pewno, że żaden z nich nie rozbił się, ponieważ zarówno A, jak i B byli w stanie zgłosić błąd. To tak, jakby jądro nagle zdecydowało się wyciągnąć wtyczkę z gniazdka z jakiegoś powodu.

Odpowiedz

3

Może spróbujesz strace jak opisano w (lub jego GUI cousin.): http://modperlbook.org/html/6-9-1-Detecting-Aborted-Connections.html

Zakładam, że problem jest związany z opisanym tutaj: http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable

Niestety, mam sam similar problem, ale nie udało mi się go naprawić za pomocą podanych wskazówek. Być może ta rzecz SO_LINGER działa dla ciebie.

+0

Okazało się, że deskryptor pliku serwera został dodany z flagą EPOLLET do kolejki epol, która wydaje się być błędna. – user206268

+2

Niezupełnie odpowiedź, której szukałem, ale strona TCP, z którą się łączyłeś, jest bardzo pouczająca! Teraz jest w archiwum Archive.org: http://ia700609.us.archive.org/22/items/TheUltimateSo_lingerPageOrWhyIsMyTcpNotReliable/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable .html – Hongli

2
  • shutdown() może zostały nazwane na jednym z gniazd końcowych.

  • Jeżeli jedna strona może widelec i wykonać proces potomny upewnić się, że flaga FD_CLOEXEC (close-on-exec) jest ustawiony na deskryptorze pliku gniazda, jeśli nie zamierza na to, aby być dziedziczone przez dziecko . W przeciwnym razie proces potomny może (przypadkowo lub w inny sposób) manipulować połączeniem z gniazdem.

+0

Dzięki, ale żadna sytuacja nie dotyczy mojego programu. – Hongli

0

Chciałbym również sprawdzić, czy nie ma podstępnej zapory ogniowej w środku. Możliwe, że pośredni węzeł przesyłający na trasie wysyła RST.Najlepszym sposobem, aby śledzić, że dół jest oczywiście the packet sniffer

+0

... na gnieździe domeny UNIX? To jest protokół lokalny. – ephemient

+0

Och ... strzelaj, całkowicie to przegapiłem. Dzięki. –

Powiązane problemy