SIGACTION(2) | Podręcznik programisty Linuksa | SIGACTION(2) |
sigaction, rt_sigaction - bada i zmienia akcję sygnału
#include <signal.h> int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
Wymagane ustawienia makr biblioteki glibc (patrz
feature_test_macros(7)):
sigaction(): _POSIX_C_SOURCE
siginfo_t: _POSIX_C_SOURCE >= 199309L
Wywołanie systemowe sigaction() jest używane do zmieniania akcji, którą odbiera proces po odebraniu określonego sygnału. (Wprowadzenie do sygnałów można znaleźć w podręczniku signals(7)).
signum określa sygnał i może być dowolnym prawidłowym sygnałem poza SIGKILL i SIGSTOP.
Jeśli act nie jest NULL-em, to nowa akcja dla sygnału signum jest brana z act. Jeśli oldact też jest różny od NULL, to poprzednia akcja jest w nim zachowywana.
Struktura sigaction jest zdefiniowana jako:
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void); };
Na niektórych architekturach część tej struktury może być unią: nie należy ustawiać jednocześnie pól sa_handler oraz sa_sigaction.
Pole sa_restorer nie jest przeznaczone do bezpośredniego stosowania (POSIX nie określa pola sa_restorer). Więcej informacji o przeznaczeniu tego pola można znaleźć w podręczniku sigreturn(2).
sa_handler podaje akcję, związaną z sygnałem signum i może to być m.in. SIG_DFL dla akcji domyślnej, SIG_IGN dla akcji ignorowania lub wskaźnik do funkcji obsługującej sygnał. Funkcja ta ma tylko jeden argument, w którym będzie przekazany numer sygnału.
Jeżeli wartość SA_SIGINFO jest podana w sa_flags, to sa_sigaction (zamiast sa_handler) określa funkcję obsługi sygnału dla signum. Funkcja ta otrzymuje numer sygnału jako pierwszy argument, wskaźnik do siginfo_t jako drugi argument oraz wskaźnik do ucontext_t (rzutowany na void *) jako jej trzeci argument (Zazwyczaj funkcja obsługi sygnału w ogóle nie używa trzeciego argumentu. Więcej informacji o ucontext_t można znaleźć w getcontext(3)).
sa_mask określa maskę sygnałów, które powinny być blokowane (tj. dodane do maski sygnałów wątku, z którego sygnał został wywołany) podczas wywoływania funkcji obsługi sygnałów. Dodatkowo, sygnał, który wywołał tę funkcję obsługi będzie zablokowany, chyba że użyto flagi SA_NODEFER.
sa_flags podaje zbiór flag, które modyfikują zachowanie procesu obsługi sygnałów. Jest to zbiór wartości połączonych bitowym OR:
Jeśli znacznik SA_NOCLDWAIT jest ustawiony podczas ustanawiania funkcji obsługującej sygnał SIGCHLD, to POSIX.1 nie określa, czy sygnał SIGCHLD po zakończeniu procesu potomnego. Pod Linuksem sygnał SIGCHLD jest w takim przypadku generowany; niektóre inne systemy go nie generują.
Argument siginfo_t z sa_sigaction jest strukturą zawierającą następujące pola:
siginfo_t {
int si_signo; /* Numer sygnału */
int si_errno; /* Wartość zmiennej errno */
int si_code; /* Kod sygnału */
int si_trapno; /* Numer pułapki, które spowodowała
sprzętowe wygenerowanie sygnału
(nieużywane na większości architektur) */
pid_t si_pid; /* ID procesu wysyłającego */
uid_t si_uid; /* Rzeczywiste ID użytk. procesu wysyłającego */
int si_status; /* Kod lub sygnał zakończenia */
clock_t si_utime; /* Czas zużyty w przestrzeni użytkownika */
clock_t si_stime; /* Czas zużyty przez system operacyjny */
sigval_t si_value; /* Wartość sygnału */
int si_int; /* Sygnał POSIX.1b */
void *si_ptr; /* Sygnał POSIX.1b */
int si_overrun; /* Licznik przekr. timerów; timery POSIX.1b */
int si_timerid; /* ID timera; timery POSIX.1b */
void *si_addr; /* Adres pamięci powodujący błąd */
long si_band; /* Grupa zdarzenia (był int w
glibc 2.3.2 i wcześniejszych) */
int si_fd; /* Deskryptor pliku */
short si_addr_lsb; /* Mniej istotny bit adresu
(od Linuksa 2.6.32) */
void *si_lower; /* Kres dolny przy wystąpieniu naruszenia
adresu (od Linuksa 3.19) */
void *si_upper; /* Kres górny przy wystąpieniu naruszenia
adresu (od Linuksa 3.19) */
int si_pkey; /* Klucz zabezpieczający na PTE będący powodem
błędu (od Linuksa 4.6) */
void *si_call_addr;/* Adres instrukcji wywołania systemowego
(od Linuksa 3.5) */
int si_syscall; /* Liczba próbowanych wywołań systemowych
(od Linuksa 3.5) */
unsigned int si_arch; /* Architektura próbowanego wywoł. systemowego
(od Linuksa 3.5) */ }
si_signo, si_errno i si_code są zdefiniowane dla wszystkich sygnałów. (Generalnie si_errno nie jest używane pod Linuksem). Pozostałe pola struktury mogą być unią; powinno się odczytywać tylko pola istotne dla danego sygnału.
Niektóre błędy pochodne SIGBUS, w szczególności BUS_MCEERR_AO i BUS_MCEERR_AR ustawiają także si_addr_lsb. Pole to oznacza najmniej znaczący bit adresu, zatem i rozmiary uszkodzeń. Na przykład jeśli cała strona została uszkodzona, si_addr_lsb zawierać będzie log2(sysconf(_SC_PAGESIZE)). Gdy jako odpowiedź na zdarzenie ptrace(2) (PTRACE_EVENT_foo) zostanie dostarczony SIGTRAP, pole si_addr nie jest wypełnione, natomiast pola si_pid i si_uid są wypełnione identyfikatorami odpowiednio procesu i użytkownika odpowiedzialnego za dostarczenie pułapki. W przypadku seccomp(2) jako dostarczenie zdarzenia pokazany zostanie zrzut. BUS_MCERR_* i si_addr_lsb są rozszerzeniami specyficznymi dla Linuksa.
SEGV_BNDERR będący podbłędem SIGSEGV wypełnia pola si_lower i si_upper.
SEGV_PKUERR będący podbłędem SIGSEGV wypełnia pole si_pkey.
si_code jest wartością (a nie maską bitową) określającą powód wysłania sygnału. Dla zdarzenia ptrace(2), pole si_code będzie zawierać SIGTRAP i mieć zdarzenie ptrace w najwyższym bajcie:
(SIGTRAP | PTRACE_EVENT_foo << 8).
W przypadku zwykłego sygnału, poniżej zestawiono wartości, które mogą występować w si_code dowolnego sygnału razem z powodami, dla których sygnał był wygenerowany.
Następujące wartości mogą zostać umieszczone w si_code sygnału SIGILL:
Następujące wartości mogą zostać umieszczone w si_code sygnału SIGFPE:
Następujące wartości mogą zostać umieszczone w si_code sygnału SIGSEGV:
Następujące wartości mogą zostać umieszczone w si_code sygnału SIGBUS:
Następujące wartości mogą zostać umieszczone w si_code sygnału SIGTRAP:
Następujące wartości mogą zostać umieszczone w si_code sygnału SIGCHLD:
Następujące wartości mogą zostać umieszczone w si_code sygnału SIGIO/SIGPOLL:
Następująca wartość może zostać umieszczona w si_code sygnału SIGSYS:
sigaction() w przypadku powodzenia zwraca 0. W razie wystąpienia błędu zwracane jest -1 i ustawiana jest zmienna errno wskazując na błąd.
POSIX.1-2001, POSIX.1-2008, SVr4.
Potomek utworzony przez fork(2) dziedziczy kopię ustawień sygnałów swojego rodzica. Podczas execve(2) ustawienia procedur obsługi sygnałów są resetowane do wartości domyślnych, z wyjątkiem sygnałów ignorowanych, które nie są zmieniane (i będą dalej ignorowane po wywołaniu execve(2)).
Zgodnie z POSIX, zachowanie procesu po zignorowaniu sygnału SIGFPE, SIGILL lub SIGSEGV, niewygenerowanego przez kill(2) lub raise(3), jest niezdefiniowane. Dzielenie liczby całkowitej przez zero ma wynik niezdefiniowany. Na niektórych architekturach generuje sygnał SIGFPE (Także dzielenie najmniejszej ujemnej liczby całkowitej przez -1 może wygenerować SIGFPE). Ignorowanie go może prowadzić do nieskończonej pętli.
POSIX.1-1990 zabraniał ustawiania akcji dla SIGCHLD na SIG_IGN. POSIX.1-2001 i późniejsze pozwalają na to, tak że można użyć ignorowania SIGCHLD, żeby zapobiec tworzeniu procesów-duchów (patrz wait(2)). Niemniej jednak, historyczne zachowanie systemów BSD i System V w zakresie ignorowania SIGCHLD jest inne, tak więc jedyną całkowicie przenośną metodą zapewnienia, że potomek po zakończeniu nie zostanie procesem-duchem jest przechwytywanie sygnału SIGCHLD i wywołanie funkcji wait(2) lub podobnej.
POSIX.1-1990 określał tylko SA_NOCLDSTOP. W POSIX.1-2001 dodano SA_NOCLDSTOP, SA_NOCLDWAIT, SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_RESTART oraz SA_SIGINFO. Używanie tych nowych wartości sa_flags może być mniej przenośne w aplikacjach przewidzianych do użycia w starszych implementacjach Uniksa.
Flaga SA_RESETHAND jest kompatybilna z flagą w SVr4 o tej samej nazwie.
Flaga SA_NODEFER jest kompatybilna z podobną flagą z SVr4 dla jąder Linuksa 1.3.9 i nowszych.
sigaction() może być wywoływany z drugim argumentem o wartości NULL, powodując w ten sposób zapytanie o bieżący handler sygnału. Może go też użyć do sprawdzenia, czy dany sygnał jest prawidłowy na obecnej maszynie. W tym celu należy zarówno drugi, jak i trzeci argument ustawić na NULL.
Nie można zablokować sygnałów SIGKILL lub SIGSTOP (przez podanie ich w sa_mask). Próby takie zostaną zignorowane.
Zobacz sigsetops(3) dla szczegółów o operacjach na zbiorach sygnałów.
Listę funkcji, które można bezpiecznie wywołać w procedurze obsługi sygnału, można znaleźć w podręczniku signal(7).
Funkcja opakowująca glibc dla sigaction() daje błąd (EINVAL) przy próbie zmiany dyspozycji dwóch sygnałów czasu rzeczywistego używanych wewnętrznie przez implementację wątkową NPTL. Więcej szczegółów w podręczniku nptl(7).
Oryginalne linuksowe wywołanie systemowe nazywało się sigaction(). Jednak po pojawieniu się sygnałów czasu rzeczywistego w Linuksie 2.2, 32-bitowy typ sigset_t o stałym rozmiarze obsługiwany przez to wywołanie przestał dobrze służyć swemu zadaniu. Z tego powodu, w celu obsługi powiększonego typu sigset_t dodano nowe wywołanie systemowe rt_sigaction(). Nowe wywołanie przyjmuje czwarty argument size_t sigsetsize, który określa rozmiar w bajtach zestawu sygnałów w act.sa_mask i oldact.sa_mask. Argument ten obecnie musi mieć wartość sizeof(sigset_t) (albo nastąpi błąd EINVAL). Opakowanie glibc sigaction() ukrywa te detale przed nami, po cichu wywołując rt_sigaction() jeśli udostępnia je jądro.
Przed wprowadzeniem SA_SIGINFO również było możliwe otrzymanie pewnych dodatkowych informacji - przez użycie sa_handler z drugim argumentem będącym typu struct sigcontext. Szczegóły można znaleźć w odpowiednich źródłach jądra Linux. To użycie jest obecnie przestarzałe.
W jądrze 2.6.13 i wcześniejszych podanie SA_NODEFER w sa_flags zapobiegało maskowaniu nie tylko dostarczonego sygnału podczas wykonywania procedury obsługi sygnału, ale także sygnałów określonych w sa_mask. Ten błąd został poprawiony w 2.6.14.
Patrz mprotect(2).
kill(1), kill(2), killpg(2), pause(2), restart_syscall(2), seccomp(2) sigaltstack(2), signal(2), signalfd(2), sigpending(2), sigreturn(2), sigprocmask(2), sigsuspend(2), wait(2), raise(3), siginterrupt(3), sigqueue(3), sigsetops(3), sigvec(3), core(5), signal(7)
Angielska wersja tej strony pochodzi z wydania 4.07 projektu Linux man-pages. Opis projektu, informacje dotyczące zgłaszania błędów, oraz najnowszą wersję oryginału można znaleźć pod adresem https://www.kernel.org/doc/man-pages/.
Autorami polskiego tłumaczenia niniejszej strony podręcznika man są: Przemek Borys (PTM) <pborys@dione.ids.pl>, Robert Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>.
Polskie tłumaczenie jest częścią projektu manpages-pl; uwagi, pomoc, zgłaszanie błędów na stronie http://sourceforge.net/projects/manpages-pl/. Jest zgodne z wersją 4.07 oryginału.
2016-03-15 | Linux |