Historia pytania:
Perl był tworzony jako język do skryptów systemowych, dlatego zarządzanie sygnałami (SIGTERM, SIGINT, SIGHUP) zawsze było wbudowaną i potężną możliwością. Ten system pozwala na przechwytywanie zewnętrznych zdarzeń (zatrzymanie przez użytkownika, ponowne uruchomienie demona, przekroczenia czasu) i mądre zakończenie lub zmianę zachowania skryptów.
Problem:
Niepoprawna obsługa sygnałów jest częstą przyczyną nieprawidłowego zakończenia lub zawieszenia skryptów, utraty danych przy awaryjnym zakończeniu, braku możliwości ponownego uruchomienia procesów bez utraty stanu lub zasobów.
Rozwiązanie:
Sygnały są obsługiwane poprzez ustawienie handlerów w specjalnym hashu %SIG. Dobrą praktyką jest minimalizm działań wewnątrz handlera sygnałów (np. ustawić flagę i bezpiecznie zakończyć w głównym wątku). Dla poprawnej pracy w wątkach i przy wielokrotnej obsłudze sygnałów używane są specjalistyczne moduły (np. POSIX::sigaction).
Przykład:
my $term = 0; $SIG{TERM} = sub { $term = 1; }; while (1) { last if $term; # główna praca } print "Graceful shutdown ";
Kluczowe cechy:
Czy można używać print/IO wewnątrz handlera sygnału?
Odpowiedź: Nie zaleca się — wystąpi nieprawidłowe działanie i możliwa utrata danych! Nowoczesny standard — minimalny kod (tylko ustalanie flag/oczyszczanie zmiennych).
Co się stanie, jeśli nie zresetujesz handlera sygnału po pierwszym uruchomieniu?
Odpowiedź: Handler będzie działał wiele razy, jeśli sygnał napłynie ponownie. Jeśli reakcja ma być tylko na pierwsze zdarzenie, handler musi samodzielnie resetować $SIG{...} lub wysyłać do siebie sygnały.
Czy obsługa sygnałów jest bezpieczna w wątkach w Perl?
Odpowiedź: Nie! W wielowątkowym Perl, handlery sygnałów są wywoływane tylko w głównym wątku (głównym interpreterze); w obrębie wątków sygnały mogą być całkowicie pominięte lub niewłaściwie obsłużone.
Proces demon przy otrzymaniu SIGTERM natychmiast wywołuje close na wszystkich deskryptorach plików i usuwa pliki tymczasowe w handlerze — od czasu do czasu pliki nie są usuwane, dane się gubią.
Zalety:
Wady:
Handler sygnału SIGTERM ustawia tylko zmienną $exit, po czym główna pętla starannie kończy pracę, zamyka pliki i dopiero potem zwalnia zasoby.
Zalety:
Wady: