Signal

Asynchroniczne powiadomienie wysyłane do procesu przez jądro lub inny proces, np. żądanie zakończenia. Proces może na większość sygnałów reagować własną obsługą.

Signal (sygnał) to asynchroniczne, jednorazowe powiadomienie wysyłane do procesu — najczęściej przez jądro systemu, ale też przez inny proces albo przez sam proces do siebie. To najprostsza forma komunikacji międzyprocesowej w systemach uniksowych: nie przenosi danych, tylko niesie informację „wydarzyło się coś, na co warto zareagować”. Klasyczny przykład to żądanie zakończenia, ale sygnał może też oznaczać błąd (np. odwołanie do nieprawidłowej pamięci), zmianę stanu procesu potomnego albo wciśnięcie Ctrl+C w terminalu.

Każdy sygnał ma numer i nazwę (np. SIGTERM = 15, SIGKILL = 9, SIGINT = 2). Gdy sygnał dotrze do procesu, jądro przerywa jego normalny bieg i sprawdza, co proces ma z nim zrobić. Na większość sygnałów proces może zareagować po swojemu — zainstalować własny handler (funkcję obsługi), zignorować sygnał albo pozwolić, żeby zadziałała akcja domyślna (zwykle zakończenie, czasem zrzut pamięci). To pozwala np. ładnie posprzątać przed wyjściem: zamknąć pliki, zapisać stan, zwolnić blokady.

Jak to działa w praktyce

Najczęściej spotkasz sygnały przez polecenie kill, które wbrew nazwie nie zabija — po prostu wysyła sygnał. kill 1234 wysyła domyślnie SIGTERM (uprzejma prośba: „zakończ się, ale ogarnij swoje sprawy”). kill -9 1234 wysyła SIGKILL — twardy strzał, którego proces nie może przechwycić ani zignorować, więc ginie natychmiast bez sprzątania.

Typowy scenarios: restartujesz usługę przez systemd. Pod spodem dostaje ona SIGTERM, jej handler zapisuje bufory i zamyka połączenia, a dopiero po TimeoutStopSec systemd dobija ją SIGKILL, jeśli wciąż żyje. W serwerach (np. nginx) SIGHUP bywa używany do przeładowania konfiguracji bez ubijania procesu. Spróbuj sam: kill -l wypisze listę wszystkich sygnałów, a man 7 signal opisze ich domyślne akcje.

Częste błędy i mity

„Wszystko da się zatrzymać przez kill -9 — owszem, ale to ostateczność. SIGKILL nie pozwala procesowi posprzątać, więc ryzykujesz uszkodzone pliki, osierocone blokady czy zombie. Najpierw SIGTERM, dopiero potem dziewiątka.

SIGKILL i SIGSTOP są nieprzechwytywalne — tych dwóch nie zignorujesz i nie obsłużysz, taki design. Proces w stanie D (uninterruptible sleep, np. zawieszony na I/O) potrafi też zignorować nawet SIGKILL, dopóki nie wróci z jądra — wtedy żadny sygnał nie pomoże poza restartem.

Uważaj też w kodzie: w handlerze sygnału wolno wołać tylko funkcje async-signal-safe. Wywołanie tam zwykłego printf czy malloc to klasyczna mina prowadząca do zakleszczenia.

Pojęcia powiązane: proces, PID, IPC (komunikacja międzyprocesowa), kill i pkill, systemd, handler sygnału, trap w skryptach shell, deskryptor pliku.