Zamykanie gniazda, które czeka proces potomny, gdy proces macierzysty został zabity

0

Sytuacja wygląda następująco:

  • Proces usługi / nadrzędny jest podłączony do „portu publicznego” (proces nadrzędny to usługa). Ten „port publiczny” to 11000. Gdy nowe żądania docierają do procesu nadrzędnego z portu 11000, serwer wysyła te żądania do procesu potomnego za pomocą „prywatnego” portu (gniazda). Wiesz, typowy sposób implementacji serwerów.

  • Proces nadrzędny zostaje zabity, ale gniazdo nie jest zamknięte (nie znam jeszcze przyczyny).

  • Proces osierocony czeka, że ​​gniazdo jest zamknięte, a pkill nie działa (jest w nieprzerwanym śnie).

  • Nie mogę ponownie uruchomić serwera, ponieważ serwer twierdzi, że adres (0.0.0.0:11000) jest już w użyciu.

Mam więc dwie opcje, aby zamknąć „gniazdo wewnętrzne”, aby zakończyć proces osierocony, lub „zwolnić” w jakiś sposób adres / port 0.0.0.0:11000, aby ponownie uruchomić serwer i pozostawić proces osierocony w stanie oczekiwania. Chodzi o to, aby unikać ponownego uruchamiania serwera za każdym razem, gdy zawiedzie, podczas gdy ja badam problem.

Przydatne informacje o sytuacji (pid procesu potomnego to 1993):

$ sudo lsof -np 1993

[...]
proc 1993 root 16u  IPv4  14997  0t0  TCP 127.0.0.1:42982->127.0.0.1:37528 (CLOSE_WAIT)

Tak więc port, którego nie chcę zamknąć, to 37528. Deskryptor pliku odpowiedniego gniazda to 16u (lub tak mi się wydaje).

$ sudo strace -p 1993

Process 1993 attached
futex(0x2fff414, FUTEX_WAIT_PRIVATE, 1, NULL

$ netstat -np
[...]
tcp      0   0 127.0.0.1:42982     127.0.0.1:37528    CLOSE_WAIT  -  

Jeśli spróbuję połączyć się z procesem osieroconym za pomocą gdb:

$ gdb -p 1993
Attaching to process 1993
{process_path} (deleted): No such file or directory.

Ponieważ proces macierzysty został zabity, tak myślę. Chodzi o to, że nie mogę połączyć się z procesem osieroconym, aby zadzwonić close(16u).

Jak mogę „rozwiązać” sytuację?

UWAGI : Próbowałem już zrestartować networkingusługę, ale nie działa. Jest to Ubuntu Server 14.04 (VirtualBox) i łączę się z moją maszyną za pomocą ssh. Nie ma menedżera sieci.

Starałem się stosować ifdown, ifupaby każdy interfejs (eth0, eth1, lo y virbr), ale nie zamyka gniazdo.

Peregring-Łk
źródło

Odpowiedzi:

1

Nie ma łatwego sposobu. Po pierwsze, nie ma to nic wspólnego z siecią : CLOSE_WAIT to status, w który wchodzi proces potomny po odpowiedzi na pakiet FIN za pomocą ACK , a przed zamknięciem gniazda i wysłaniem do swojego partnera pakietu FIN . Podczas stanu CLOSE_WAIT proces kończy operację, na końcu której wywoła close () , która zachęca jądro do wysłania pakietu FIN.

Innymi słowy, podczas stanu CLOSE_WAIT proces próbuje wykonać jakąś operację, nie czekając na coś od partnera; dlatego zamknięcie sieci, ponowne uruchomienie interfejsów i tak dalej nic nie da.

Zasadniczo nie powinno to stanowić poważnego problemu: nie ma nic złego w zawieszaniu niektórych procesów w stanie CLOSE_WAIT . Trudno jest zrozumieć to, co Ci przeszkadza: stwierdzasz, że proces nadrzędny nasłuchuje na porcie 11000, a następnie kontaktuje się z dzieckiem na porcie 37528, ale stwierdzasz, że po śmierci procesu nadrzędnego nie można uruchomić nowej instancji serwera, ponieważ port 11000 nie został zwolniony. Ale właśnie powiedziałeś, że to nie proces potomny go używa! Kim więc jest?

W każdym razie możesz wypróbować tylko kilka rzeczy;

  1. próbowałeś zabić proces z opcją -9 ? To najsilniejszy, jaki możesz wymyślić.

  2. Możesz używać strace od początku do śledzenia wywołań systemowych nawet w procesach potomnych (czy to procesach potomnych?) Za pomocą

    strace -f YourParentProcess
    

    Będzie to również postępować zgodnie z procesami * fork () * ed.

  3. Domyślam się, że możesz równie dobrze zapomnieć o dziecku i spróbować ustalić, dlaczego port 11000 wydaje się być zajęty i przez kogo. Powinieneś spróbować wygodniejszego polecenia

    ss -lntp | grep 11000
    

    zbadać sprawę.

MariusMatutiae
źródło