Nie możesz ufać, że każdy wysłany sygnał zostanie dostarczony. Na przykład jądro Linuksa „łączy” SIGCHLD, jeśli proces zajmuje dużo czasu w obsłudze SIGCHLD z zakończonego procesu potomnego.
Aby odpowiedzieć na inną część twojego pytania, sygnały zostają „umieszczone w kolejce” wewnątrz jądra, jeśli liczba różnych sygnałów dotrze w zbyt krótkim odstępie czasu.
Należy użyć sigaction()
, aby ustawić obsługi sygnału z sa_sigaction
członka siginfo_t
, ustawienie sa_mask
członek siginfo_t
starannie argument. Myślę, że oznacza to maskowanie przynajmniej wszystkich sygnałów „asynch”. Według strony podręcznika użytkownika dla Linuksa sigaction()
ukryjesz również przetwarzany sygnał. Myślę, że powinieneś ustawić sa_flags
członka na SA_SIGINFO, ale nie pamiętam, dlaczego mam takie przesądy. Wierzę, że dzięki temu twój proces będzie obsługiwał sygnał, który pozostanie ustawiony bez warunków wyścigu i taki, który nie zostanie przerwany przez większość innych sygnałów.
Napisz swoją funkcję obsługi sygnału bardzo, bardzo ostrożnie. Zasadniczo wystarczy ustawić zmienną globalną, aby wskazać, że sygnał został złapany, a reszta procesu zajmie się żądaną akcją dla tego sygnału. W ten sposób sygnały będą maskowane przez jak najmniej czasu.
Ponadto bardzo dokładnie przetestujesz kod obsługi sygnału. Przeprowadź go w małym procesie testowym i wyślij jak najwięcej sygnałów SIGUSR1 i SIGUSR2, na przykład z 2 lub 3 programów do wysyłania sygnałów specjalnego przeznaczenia. Miksuj także inne sygnały, gdy masz pewność, że Twój kod może szybko i poprawnie obsługiwać SIGUSR1 i SIGUSR2. Przygotuj się na trudne debugowanie.
Jeśli używasz Linuksa i tylko Linuksa, możesz pomyśleć o signalfd()
utworzeniu deskryptora pliku, który możesz select()
lub odpytać, aby odebrać te sygnały. Użycie signalfd()
może ułatwić debugowanie.
signal(2)
podręcznika Linuksa dla sugeruje zdecydowanie, aby uniknąć tego zamieszania, używającsigaction(2)
zamiast tego.