sigaction(2)

NAZWA
sigaction, rt_sigaction - bada i zmienia akcję sygnału

BIBLIOTEKA
Standardowa biblioteka C (libc, -lc)

SKŁADNIA
#include <signal.h>

int sigaction(int signum,
              const struct sigaction *_Nullable restrict act,
              struct sigaction *_Nullable restrict oldact);

    Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)):

sigaction():
    _POSIX_C_SOURCE

siginfo_t:
    _POSIX_C_SOURCE >= 199309L

OPIS
Wywołanie systemowe sigaction() jest używane do zmieniania akcji, którą wykonuje 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 określa akcję, jaka ma być powiązana z signum i może być to jedna z:

•   SIG_DFL aby uzyskać domyślną akcję.

•   SIG_IGN aby ignorować ten sygnał.

•   Wskaźnik do funkcji obsługującej sygnał. Funkcja ta ma tylko jeden argument, w którym będzie przekazany numer sygnału.

Jeśli w sa_flags poda się SA_SIGINFO, to sa_sigaction (zamiast sa_handler) będzie określało funkcję obsługi sygnału signum. Funkcja ta ma trzy argumenty, opisane poniżej.

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 znacznika SA_NODEFER.

sa_flags podaje zbiór znaczników, które modyfikują zachowanie procesu obsługi sygnałów. Jest to zbiór wartości połączonych bitowym OR:

SA_NOCLDSTOP
    Jeśli signum jest równe SIGCHLD, to nie są odbierane powiadomienia o zatrzymaniu procesu potomnego (np. gdy potomek otrzyma jeden z SIGSTOP, SIGTSTP, SIGTTIN lub SIGTTOU) ani o jego wznowieniu (np. po otrzymaniu SIGCONT) (patrz wait(2)). Znacznik ten ma znaczenie tylko w przypadku ustawiania funkcji obsługi sygnału SIGCHLD.

SA_NOCLDWAIT (od Linuksa 2.6)
    Jeśli signum jest równy SIGCHLD, to potomkowie po swoim zakończeniu nie zostaną przekształceni w zombie. Patrz także waitpid(2). Znacznik ma znaczenie tylko dla ustanawiania funkcji obsługującej sygnał SIGCHLD lub podczas ustawiania tego sygnału na SIG_DLF.

    Jeśli znacznik SA_NOCLDWAIT jest ustawiony podczas ustanawiania funkcji obsługującej sygnał SIGCHLD, to POSIX.1 nie określa, czy sygnał SIGCHLD jest generowany po zakończeniu procesu potomnego. Pod Linuksem sygnał SIGCHLD jest w takim przypadku generowany; niektóre inne systemy go nie generują.

SA_NODEFER
    Nie dodaje sygnału do maski sygnałów wątku, gdy wykonywana jest funkcja obsługi sygnału, chyba że w act.sa_mask podano sygnał. Kolejne wystąpienie sygnału może zatem być dostarczone do wątku, w czasie wykonywania funkcji obsługi sygnału. Znacznik ten ma znaczenie tylko w przypadku ustanawiania funkcji obsługi sygnału.

    SA_NOMASK jest przestarzałym, niestandardowym synonimem tego znacznika.

SA_ONSTACK
    Wywołuje funkcję obsługi sygnału, używając alternatywnego stosu ustawionego przez sigaltstack(2). Jeżeli ten alternatywny stos nie jest dostępny, zostanie użyty stos domyślny. Znacznik ten ma znaczenie tylko w przypadku ustanawiania funkcji obsługi sygnału.

SA_RESETHAND
    Odtwarza akcję sygnałową do stanu domyślnego po wejściu funkcji obsługi sygnału. Znacznik ten ma znaczenie tylko w przypadku ustanawiania funkcji obsługi sygnału.

    SA_ONESHOT jest przestarzałym, niestandardowym synonimem tego znacznika.

SA_RESTART
    Dostarcza zachowania kompatybilnego z semantyką sygnałową BSD, czyniąc pewne wywołania systemowe odtwarzalnymi przez sygnały. Znacznik ten ma znaczenie podczas ustanawiania procedury obsługi sygnału. Informacje na temat odtwarzania wywołań systemowych można znaleźć w podręczniku signal(7).

SA_RESTORER
    Nie jest przeznaczone do bezpośredniego stosowania. Znacznik ten jest używany przez biblioteki C do wskazania, że pole sa_restorer zawiera adres „trampoliny sygnału”. Więcej szczegółów w podręczniku sigreturn(2).

SA_SIGINFO (od Linuksa 2.2)
    Funkcja obsługi sygnałów pobiera trzy argumenty, a nie jeden. W tym przypadku zamiast ustawiać sa_handler należy ustawić sa_sigaction. Znacznik ten ma znaczenie tylko w przypadku ustanawiania funkcji obsługi sygnału.

SA_UNSUPPORTED (od Linuksa 5.11)
    Używany do dynamicznego sprawdzania obsługiwanych bitów znaczników.

    Jeśli próba zarejestrowania procedury obsługi — z tym znacznikiem ustawionym w act->sa_flags wraz z innymi znacznikami, które mogą być nieobsługiwane przez jądro — powiedzie się, a najbliższe wywołanie sigaction(), które poda ten sam numer sygnału z argumentem oldact innym niż NULL spowoduje wyczyszczenie SA_UNSUPPORTED z oldact->sa_flags, to oldact->sa_flags można użyć jako mapy bitowej znaczników wskazującej, które z potencjalnie nieobsługiwanych znaczników są w rzeczywistości obsługiwane. Więcej informacji znajduje się w rozdziale „Dynamiczne sprawdzanie obsługiwanych bitów znaczników” poniżej.

SA_EXPOSE_TAGBITS (od Linuksa 5.11)
    Przy dostarczaniu sygnału, zestaw bitów znaczników charakterystycznych dla architektury jest zwykle czyszczony z pola si_addr siginfo_t. Jeśli ten znacznik jest ustawiony, podzbiór bitów znaczników charakterystycznych dla architektury zostanie zachowany w si_addr.

    Programy, które muszą być kompatybilne z wersjami Linuksa starszymi niż 5.11, muszą użyć SA_UNSUPPORTED aby sprawdzić dostępność obsługi tego znacznika.

  Argument siginfo_t do procedury obsługi SA_SIGINFO
Gdy w act.sa_flags poda się znacznik SA_SIGINFO, to adres procedury obsługi sygnału jest przekazywany za pomocą pola act.sa_sigaction. Ta procedura obsługi przyjmuje trzy argumenty jak poniżej:

    void
    handler(int sig, siginfo_t *info, void *ucontext)
    {
        ...
    }

Te trzy argumenty to:

sig Numer sygnału powodującego przywołanie procedury obsługi.

info
    Wskaźnik do siginfo_t, który jest strukturą zawierającą dalsze informacje o sygnale, jak to opisano poniżej.

ucontext
    Jest to wskaźnik do struktury ucontext_t rzutowany na void *. Struktura, na którą wskazuje to pole zawiera informacje o kontekście sygnału, które zostały zachowanie w stosie w przestrzeni użytkownika przez jądro; więcej szczegółów w podręczniku sigreturn(2). Dalsze informacje o strukturze ucontext_t można odszukać w podręcznikach getcontext(3) i signal(7). Funkcja obsługi nie czyni zwykle żadnego użytku z trzeciego argumentu.

Typ danych siginfo_t 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 użyty w przestrzeni użytkownika */
        clock_t  si_stime;    /* Czas użyty przez system operacyjny */
        union sigval si_value;  /* Wartość sygnału */
        int      si_int;      /* Sygnał POSIX.1b */
        void    *si_ptr;      /* Sygnał POSIX.1b */
        int      si_overrun;  /* Licznik przekr. czasom.; czasom POSIX.1b */
        int      si_timerid;  /* ID czasomierza; czasom. 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; /* Najmniej znaczący 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.

•   Sygnały wysłane przez kill(2) i sigqueue(3) mają wypełnione pola si_pid oraz si_uid. Dodatkowo sygnały wysłane przez sigqueue(3) mają w polach si_int i si_ptr ustawione wartości podane przez nadawcę sygnału; szczegóły opisano w sigqueue(3).

•   Sygnały wysłane przez czasomierze POSIX.1b (od Linuksa 2.6) mają uzupełnione pola si_overrun i si_timerid. Pole si_timerid zawiera wewnętrzny identyfikator używany przez jądro do identyfikacji czasomierza; nie jest to ten sam identyfikator, który zwraca timer_create(2). Pole si_overrun zawiera informację o tym, ile razy czasomierz się przepełnił — jest to ta sama informacja, którą zwraca timer_getoverrun(2). Pola te są niestandardowymi rozszerzeniami Linuksa.

•   Sygnały wysłane w celu notyfikacji kolejki komunikatów (patrz opis SIGEV_SIGNAL in mq_notify(3)) mają pola si_int/si_ptr wypełnione wartościami sigev_value przekazanymi do mq_notify(3); ponadto si_pid zawiera identyfikator procesu wysyłającego sygnał, a si_uid rzeczywisty identyfikator użytkownika - nadawcy sygnału.

•   SIGCHLD ustawia pola si_pid, si_uid, si_status, si_utime i si_stime, dostarczając informacji o procesie potomnym. Pole si_pid jest identyfikatorem potomka, si_uid jest rzeczywistym identyfikatorem użytkownika procesu potomnego. Pole si_status zawiera kod zakończenia potomka (jeśli si_code jest równe CLD_EXITED) lub numer sygnału, który spowodował zmianę stanu. Pola si_utime i si_stime zawierają czasy spędzone przez potomka w przestrzeniach użytkownika i systemowej; w przeciwieństwie do getrusage(2) i times(2), pola te nie zawierają czasów oczekiwania na potomków. Do Linuksa 2.6 oraz od Linuksa 2.6.27, pola zawierają czas CPU w jednostkach sysconf(_SC_CLK_TCK). W Linuksie 2.6 przed Linuksem 2.6.27 z powodu błędu używane były (konfigurowalne) jednostki jiffy (patrz time(7)).

•   SIGILL, SIGFPE, SIGSEGV, SIGBUS oraz SIGTRAP wypełniają pole si_addr, ustawiając w nim adres błędu. Na niektórych architekturach sygnały wypełniają także pole si_trapno.

    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.

•   SIGIO/SIGPOLL (te dwie nazwy są synonimami pod Linuksem) wypełnia pola si_band i si_fd. Zdarzenie si_band jest maską bitową zawierającą te same wartości, które poll(2) umieszcza w polu revents. Pole si_fd oznacza deskryptor pliku, na którym wystąpiło dane zdarzenie wejścia/wyjścia; więcej szczegółów w opisie F_SETSIG w podręczniku fcntl(2).

•   SIGSYS, generowany (od Linuksa 3.5) gdy filtr seccomp zwróci SECCOMP_RET_TRAP, wypełnia pola si_call_addr, si_syscall, si_arch, si_errno i inne, zgodnie z opisem z seccomp(2).

  Pole si_code
Pole si_code, wewnątrz argumentu siginfo_t, które jest przekazywane do procedury obsługi sygnału SA_SIGINFO, 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).

Dla zdarzeń innych niż ptrace(2), wartości jakie mogą wystąpić w si_code są opisane w pozostałej części niniejszego rozdziału. Od glibc 2.20, definicje większości z tych symboli są pozyskiwane z <signal.h> za pomocą definicji makr testowania cech (przed włączeniem jakiegokolwiek pliku nagłówkowego), jak poniżej:

•   _XOPEN_SOURCE z wartością 500 lub większą;

•   _XOPEN_SOURCE i _XOPEN_SOURCE_EXTENDED; albo

•   _POSIX_C_SOURCE z wartością 200809L lub większą.

Dla stałych TRAP_*, definicje symboli są zapewnione jedynie w dwóch pierwszych przypadkach. Przed glibc 2.20, nie było konieczne ustawianie makr, do pozyskania tych symboli.

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.

    SI_USER
        kill(2).

    SI_KERNEL
        Wysyłany przez jądro.

    SI_QUEUE
        sigqueue(3).

    SI_TIMER
        Wygasł czasomierz POSIX lub setitimer(2) lub alarm(2).

    SI_MESGQ (od Linuksa 2.6.6)
        Zmiana stanu kolejki komunikatów POSIX; patrz mq_notify(3)

    SI_ASYNCIO
        Ukończenie asynchronicznej operacji wejścia/wyjścia.

    SI_SIGIO
        Kolejkowany SIGIO (tylko do Linuksa 2.2; od Linuksa 2.4 SIGIO/SIGPOLL wypełniają si_code, tak jak to opisano poniżej).

    SI_TKILL (od Linuksa 2.4.19)
        tkill(2) lub tgkill(2)

    SI_ASYNCNL
        Ukończenie asynchronicznego wyszukiwania nazw.

Następujące wartości mogą zostać umieszczone w si_code sygnału SIGILL:

    ILL_ILLOPC
        Niedozwolony kod operacji.

    ILL_ILLOPN
        Niedozwolony operand.

    ILL_ILLADR
        Niedozwolony tryb adresowania.

    ILL_ILLTRP
        Niedozwolona pułapka.

    ILL_PRVOPC
        Uprzywilejowany kod operacji.

    ILL_PRVREG
        Uprzywilejowany rejestr.

    ILL_COPROC
        Błąd koprocesora.

    ILL_BADSTK
        Wewnętrzny błąd stosu.

Następujące wartości mogą zostać umieszczone w si_code sygnału SIGFPE:

    FPE_INTDIV
        Dzielenie wartości całkowitej przez zero.

    FPE_INTOVF
        Przepełnienie liczby całkowitej.

    FPE_FLTDIV
        Dzielenie wartości zmiennoprzecinkowej przez zero.

    FPE_FLTOVF
        Przekroczenie zakresu operacji zmiennoprzecinkowej.

    FPE_FLTUND
        Przekroczenie (w dół) zakresu operacji zmiennoprzecinkowej.

    FPE_FLTRES
        Niedokładny wynik operacji zmiennoprzecinkowej.

    FPE_FLTINV
        Niepoprawna operacja zmiennoprzecinkowa.

    FPE_FLTSUB
        Dolny indeks poza zakresem.

    FPE_FLTUNK (od Linuksa 4.17)
        Niezdiagnozowany wyjątek zmiennoprzecinkowy.

    FPE_CONDTRAP (tylko PARISC)
        Pułapka przy warunku.

Następujące wartości mogą zostać umieszczone w si_code sygnału SIGSEGV:

    SEGV_MAPERR
        Adres niemapowany do obiektu.

    SEGV_ACCERR
        Niepoprawne uprawnienia mapowanego obiektu.

    SEGV_BNDERR (od Linuksa 3.19)
        Niepowodzenie sprawdzenia przypisania adresu.

    SEGV_PKUERR (od Linuksa 4.6)
        Dostęp został odmówiony przez klucze zabezpieczeń pamięci. Zob. pkeys(7). Klucz zabezpieczeń, jaki zastosowano do tego dostępu jest dostępny za pomocą si_pkey.

    SEGV_ACCADI (od Linuksa 4.17; tylko SPARC)
        Dla zmapowanego obiektu nie włączono mechanizmu integralności danych aplikacji (ADI).

    SEGV_ADIDERR (od Linuksa 4.17; tylko SPARC)
        Błąd naruszającego wykrywania uszkodzeń pamięci.

    SEGV_ADIPERR (od Linuksa 4.17; tylko SPARC)
        Wyjątek precyzyjnego wykrywania uszkodzeń pamięci.

    SEGV_MTEAERR (od Linuksa 5.10; tylko ARM)
        Błąd asynchronicznego rozszerzenia oznaczania pamięci (MTE).

    SEGV_MTESERR (od Linuksa 5.10; tylko ARM)
        Wyjątek synchronicznego rozszerzenia oznaczania pamięci (MTE).

    SEGV_CPERR (od Linuksa 6.10)
        Naruszenie zabezpieczenia kontroli.

Następujące wartości mogą zostać umieszczone w si_code sygnału SIGBUS:

    BUS_ADRALN
        Niepoprawne wyrównanie adresu.

    BUS_ADRERR
        Nieistniejący adres fizyczny.

    BUS_OBJERR
        Błąd sprzętowy specyficzny dla obiektu.

    BUS_MCEERR_AR (od Linuksa 2.6.32)
        Sprzętowy błąd pamięci podczas sprawdzania komputera; wymagane podjęcie akcji.

    BUS_MCEERR_AO (od Linuksa 2.6.32)
        Wykryto sprzętowy błąd pamięci w procesie; opcjonalne podjęcie akcji.

Następujące wartości mogą zostać umieszczone w si_code sygnału SIGTRAP:

    TRAP_BRKPT
        Punkt wstrzymania procesu.

    TRAP_TRACE
        Śledzony proces złapany.

    TRAP_BRANCH (od Linuksa 2.4; tylko IA64)
        Śledzone rozgałęzienie procesu złapane.

    TRAP_HWBKPT (od Linuksa 2.4; tylko IA64)
        Pułapka sprzętowa.

    TRAP_UNK (od Linuksa 4.18)
        Niezdiagnozowana pułapka.

    TRAP_PERF (od Linuksa 5.13 i glibc 2.43)
        Zdarzenie perf z sigtrap=1.

Następujące wartości mogą zostać umieszczone w si_code sygnału SIGCHLD:

    CLD_EXITED
        Proces potomny się zakończył.

    CLD_KILLED
        Proces potomny został zabity.

    CLD_DUMPED
        Potomek zakończył się w nieprawidłowy sposób.

    CLD_TRAPPED
        Śledzony potomek został złapany.

    CLD_STOPPED
        Proces potomny został zatrzymany.

    CLD_CONTINUED (od Linuksa 2.6.9)
        Zatrzymany proces potomny został wznowiony.

Następujące wartości mogą zostać umieszczone w si_code sygnału SIGIO/SIGPOLL:

    POLL_IN
        Dostępne dane na wejściu.

    POLL_OUT
        Dostępne bufory wyjścia.

    POLL_MSG
        Dostępna wiadomość na wejściu.

    POLL_ERR
        Błąd wejścia/wyjścia.

    POLL_PRI
        Dostępne wejście o wysokim priorytecie.

    POLL_HUP
        Urządzenie odłączone.

Następujące wartości mogą zostać umieszczone w si_code sygnału SIGSYS:

    SYS_SECCOMP (od Linuksa 3.5 i glibc 2.43)
        Wyzwolone przez regułę filtra seccomp(2).

    SYS_USER_DISPATCH (od Linuksa 5.11 i glibc 2.43)
        Wyzwolono dostarczanie wywołań systemowych do przestrzeni użytkownika.

Następująca wartość może zostać umieszczona w si_code sygnału SIGEMT:

    EMT_TAGOVF (tylko SPARC)
        Przepełnienie znacznika.

  Dynamiczne sprawdzanie obsługiwanych bitów znaczników
Wywołanie sigaction() w Linuksie akceptuje nieznane bity ustawione w act->sa_flags nie zgłaszając błędu. Zachowanie jądra, od Linuksa 5.11 jest takie, że drugie sigaction() wyczyści nieznane bity z oldact->sa_flags. Jednak historycznie, drugie wywołanie zwykle pozostawiało te bity ustawione w oldact->sa_flags.

Oznacza to, że nie da się wykryć obsługi nowych znaczników jedynie sprawdzając znacznik w sa_flags, lecz konieczne jest sprawdzenie, czy SA_UNSUPPORTED zostało wyczyszczone, przed poleganiem na zawartości sa_flags.

Ponieważ zachowania procedury obsługi sygnału nie można zagwarantować, jeśli nie dokonano sprawdzenia, powinno się albo blokować dany sygnał podczas rejestrowania procedury obsługi i wykonać w takim przypadku sprawdzenie, albo — tam, gdzie nie jest to możliwe, np. gdy sygnał jest asynchroniczny — wywołać sigaction() po raz drugi z samej procedury obsługi sygnału.

W jądrach nieobsługujących danego znacznika, jądro zachowa się tak, jakby znacznik ten nie był ustawiony, nawet jeśli znacznik był ustawiony w act->sa_flags.

Znaczników SA_NOCLDSTOP, SA_NOCLDWAIT, SA_SIGINFO, SA_ONSTACK, SA_RESTART, SA_NODEFER, SA_RESETHAND i, jeśli jest zdefiniowany na danej architekturze, SA_RESTORER nie da się wiarygodnie sprawdzić za pomocą opisywanego mechanizmu, ponieważ zostały one wprowadzone przez Linuksem 5.11. Zwykle jednak, programy mogą przyjąć, że znaczniki te są obsługiwane, ponieważ wszystkie były obsługiwane już od Linuksa 2.6, wydanego w roku 2003.

W rozdziale PRZYKŁADY poniżej, zademonstrowano korzystanie z SA_UNSUPPORTED.

WARTOŚĆ ZWRACANA
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.

BŁĘDY

EFAULT
    act lub oldact wskazują na pamięć poza przestrzenią adresową procesu.

EINVAL
    Podano nieprawidłowy sygnał. Będzie to też generowane w przypadku próby zmienienia akcji dla sygnałów SIGKILL lub SIGSTOP, które nie mogą być przechwycone lub zignorowane.

WERSJE

  Różnice biblioteki C/jądra
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).

Na architekturach, na których trampolina sygnału jest zawarta w bibliotece C, funkcja opakowujące sigaction() z glibc, umieszcza adres kodu trampoliny w polu act.sa_restorer i ustawia znacznik SA_RESTORER w polu act.sa_flags. Zob. sigreturn(2).

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.

STANDARDY
POSIX.1-2024.

HISTORIA
POSIX.1-2001, SVr4.

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 zombie (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 zombie 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_NOCLDWAIT, SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_RESTART i SA_SIGINFO jako rozszerzenia XSI. POSIX.1-2008 przeniósł SA_NODEFER, SA_RESETHAND, SA_RESTART i SA_SIGINFO do głównej normy. Używanie tych nowych wartości sa_flags może być mniej przenośne w aplikacjach przewidzianych do użycia w starszych implementacjach Uniksa.

Znacznik SA_RESETHAND jest kompatybilny ze znacznikiem w SVr4 o tej samej nazwie.

Znacznik SA_NODEFER jest kompatybilny z podobnym znacznikiem z SVr4 dla Linuksa 1.3.9 i nowszych. Na starszych jądrach implementacja Linuksa pozwalała na otrzymanie dowolnego sygnału, nie tylko tego instalowanego (w praktyce przesłaniając ustawienie sa_mask).

UWAGI
Potomek utworzony przez fork(2) dziedziczy kopię ustawień sygnałów od swojego rodzica. Podczas wywołania execve(2) przywracane są wartości domyślne ustawień, z wyjątkiem ustawienia ignorowania sygnału, które nie jest zmieniane.

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.

sigaction() może być wywoływany z drugim argumentem o wartości NULL, powodując w ten sposób zapytanie o bieżącą procedurę obsługi 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 są async-signal-safe i można je bezpiecznie wywołać w procedurze obsługi sygnału, można znaleźć w podręczniku signal-safety(7).

POSIX gwarantuje jedynie SI_TIMER w przypadku sygnałów utworzonych za pomocą timer_create(2). Implementacje mogą go dostarczać również w przypadku innych typów czasomierzy. Zachowanie Linuksa odpowiada NetBSD.

  Nieudokumentowane
Przed wprowadzeniem SA_SIGINFO również było możliwe otrzymanie pewnych dodatkowych informacji o sygnale. Działo się to poprzez użycie procedury obsługi sygnału sa_handler z drugim argumentem, będącym typu struct sigcontext, który jest taką samą strukturą jak ta przekazywana w polu uc_mcontext struktury ucontext, przekazywanym (wskaźnikiem) w trzecim argumencie procedury obsługi sa_sigaction. Szczegóły można znaleźć w odpowiednich źródłach jądra Linux. To użycie jest obecnie przestarzałe.

USTERKI
Przy dostarczaniu sygnału wynikającego z wyjątku sprzętowego z procedurą obsługi SA_SIGINFO, jądro nie zawsze zapewnia sensowne wartości dla wszystkich pól siginfo_t, które są istotne dla tego sygnału. Na przykład, gdy instrukcja x86 int jest wywoływana z niedozwolonym argumentem (liczbą inną niż 3 lub 128), dostarczany jest sygnał SIGSEGV, lecz siginfo_t przekazywane do procedury obsługi sygnału ma wszystkie swe pola poza si_signo i si_code ustawione na zero, nawet gdy inne pola powinny być ustawione (np. si_addr powinno być niezerowe dla wszystkich sygnałów SIGSEGV).

Do Linuksa 2.6.13 włącznie, 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 Linuksie 2.6.14.

PRZYKŁADY
Patrz mprotect(2).

  Sprawdzanie obsługiwanych znaczników
Poniższy przykładowy program wychodzi ze statusem EXIT_SUCCESS gdy sprawdzi, że SA_EXPOSE_TAGBITS jest obsługiwany albo EXIT_FAILURE w przeciwnym przypadku.

    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>

    static void
    handler(int signo, siginfo_t *info, void *context)
    {
        struct sigaction oldact;

        if (sigaction(SIGSEGV, NULL, &oldact) == -1
            || (oldact.sa_flags & SA_UNSUPPORTED)
            || !(oldact.sa_flags & SA_EXPOSE_TAGBITS))
        {
            _exit(EXIT_FAILURE);
        }
        _exit(EXIT_SUCCESS);
    }

    int
    main(void)
    {
        struct sigaction act = { 0 };

        act.sa_flags = SA_SIGINFO | SA_UNSUPPORTED | SA_EXPOSE_TAGBITS;
        act.sa_sigaction = &handler;
        if (sigaction(SIGSEGV, &act, NULL) == -1) {
            perror("sigaction");
            exit(EXIT_FAILURE);
        }

        raise(SIGSEGV);
    }

ZOBACZ TAKŻE
kill(1), kill(2), pause(2), pidfd_send_signal(2), restart_syscall(2), seccomp(2), sigaltstack(2), signal(2), signalfd(2), sigpending(2), sigprocmask(2), sigreturn(2), sigsuspend(2), wait(2), killpg(3), raise(3), siginterrupt(3), sigqueue(3), sigsetops(3), sigvec(3), core(5), signal(7)

TŁUMACZENIE
Tłumaczenie niniejszej strony podręcznika: Przemek Borys <pborys@dione.ids.pl>, Robert Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>

Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 (https://www.gnu.org/licenses/gpl-3.0.html) lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.

Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.