Na StackOverflow znajduje się świetna odpowiedź na temat zapewnienia lepszej blokady demonów (zsyntetyzowanej przez Eduardo Fleury ), która nie zależy od wspólnego mechanizmu blokowania plików PID dla demonów. Istnieje wiele dobrych komentarzy na temat tego, dlaczego pliki blokujące PID mogą czasami powodować problemy, więc nie będę ich tutaj ponownie przeglądać.
Krótko mówiąc, rozwiązanie opiera się na gniazdach domeny abstrakcyjnej przestrzeni nazw systemu Linux, które śledzą gniazda według nazwy, a nie na plikach, które mogą pozostać po SIGKILL'ie demona. Przykład pokazuje, że Linux wydaje się zwalniać gniazdo po zakończeniu procesu.
Ale nie mogę znaleźć ostatecznej dokumentacji w systemie Linux, która mówi, co dokładnie Linux robi z gniazdem abstrakcyjnym, gdy związany proces jest SIGKILL. Czy ktoś wie?
Innymi słowy, kiedy dokładnie abstrakcyjne gniazdo może zostać ponownie użyte?
Nie chcę zastępować mechanizmu pliku PID abstrakcyjnymi gniazdami, chyba że ostatecznie rozwiąże problem.
źródło
Odpowiedzi:
Tak, linux automatycznie „czyści” abstrakcyjne gniazda do tego stopnia, że nawet czyszczenie ma sens. Oto minimalny działający przykład, za pomocą którego możesz to zweryfikować:
Uruchom ten program jako
./a.out /test-socket &
, a następnie uruchomss -ax | grep test-socket
, a zobaczysz używane gniazdo. Wtedykill %./a.out
, iss -ax
pokaże gniazdko nie ma.Jednak powodem, dla którego nie można znaleźć takiego czyszczenia w żadnej dokumentacji, jest to, że tak naprawdę nie jest to czyszczenie w tym samym sensie, co nie abstrakcyjne gniazda w domenie unixowej wymagają czyszczenia. Nie-abstrakcyjne gniazdo faktycznie przydziela i-węzeł i tworzy wpis w katalogu, który należy wyczyścić w podstawowym systemie plików. Pomyśl o abstrakcyjnym gnieździe bardziej przypominającym numer portu TCP lub UDP. Jasne, jeśli powiążesz port TCP, a następnie wyjdziesz, ten port TCP znów będzie wolny. Ale jakikolwiek numer 16-bitowy, którego użyłeś, nadal istnieje abstrakcyjnie i zawsze istniał. Przestrzeń nazw numerów portów to 1-65535 i nigdy się nie zmienia ani nie wymaga czyszczenia.
Pomyśl więc o abstrakcyjnej nazwie gniazda, takiej jak numer portu TCP lub UDP, wybrany z dużo większego zestawu możliwych numerów portów, które wyglądają jak nazwy ścieżek, ale nimi nie są. Nie można powiązać tego samego numeru portu dwa razy (blokowanie
SO_REUSEADDR
lubSO_REUSEPORT
). Ale zamknięcie gniazda (jawnie lub niejawnie przez zakończenie) uwalnia port, nie pozostawiając nic do wyczyszczenia.źródło
Zadałem to pytanie ponad rok temu i nigdy nie byłem zadowolony z braku ostatecznej dokumentacji. Pomyślałem, że ponownie sprawdzę dokumentację Linuksa pod kątem aktualizacji i cieszę się, widząc to :
Również interfejs programowania Linuksa autorstwa Michaela Kerrisk obejmuje pytanie (zamieszczone w innej odpowiedzi ):
Uważam, że wraz z odpowiedzią @ user3188445 rozwiązuje to pytanie bardzo dokładnie.
To powiedziawszy, nadal istnieje założenie, że wszystkie procesy, które są SIGKILL, będą miały zamknięte wszystkie otwarte gniazda. To wydaje się rozsądnym założeniem, ale nie mam dokumentacji, która definiowałaby to zachowanie.
źródło
SOCK_CLOEXEC
na wypadek, gdyby jakikolwiek kod (w tym biblioteka) kiedykolwiek używał fork () + exec (). Tworzenie dodatkowych procesów potomnych za pomocą fork () bez exec () jest mniej powszechne; prawdopodobnie już wiesz, czy to robisz.