sigaction(2) | System Calls Manual | sigaction(2) |
sigaction, rt_sigaction - Signalaktionen untersuchen und ändern
Standard-C-Bibliothek (libc, -lc)
#include <signal.h>
int sigaction(int signum, const struct sigaction *_Nullable restrict akt, struct sigaction *_Nullable restrict altakt);
sigaction():
_POSIX_C_SOURCE
siginfo_t:
_POSIX_C_SOURCE >= 199309L
Der Systemaufruf sigaction wird zur Veränderung der von einem Prozess beim Empfang eines Signals durchgeführten Aktion benutzt. (Siehe signal(7) für einen Überblick über Signale.)
signum legt das Signal fest und kann jedes gültige Signal außer SIGKILL und SIGSTOP sein.
Falls akt nicht NULL ist, wird die neue Aktion für Signal signum aus akt installiert. Falls altakt nicht NULL ist, wird die vorherige Aktion in altakt gespeichert.
Die Struktur sigaction wird durch etwas wie das folgende definiert:
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void); };
Auf einigen Architekturen ist eine Union beteiligt; weisen Sie diese nicht sowohl sa_handler als auch sa_sigaction zu.
Das Feld sa_restorer ist nicht zur Verwendung durch Anwendungen gedacht. (POSIX spezifiziert ein Feld sa_restorer nicht.) Weitere Details über den Zweck dieses Feldes finden Sie in sigreturn(2).
sa_handler bestimmt die Aktion, die signum zugeordnet werden soll und kann eine der folgenden sein:
Falls SA_SIGINFO in sa_flags festgelegt ist, dann legt sa_sigaction (statt sa_handler) die Signal-Handhabungsfunktion für signum fest. Diese Funktion empfängt wie unten beschrieben drei Argumente.
sa_mask legt eine Signalmaske fest, die angibt, welche Signale während der Ausführung der Signalhandhabungsfunktion blockiert (d.h. zu der Signalmaske des Threads, in der der Signal-Handler aufgerufen wird, hinzugefügt) werden sollen. Zusätzlich wird das Signal, das den Handler ausgelöst hat, blockiert, falls nicht der Schalter SA_NODEFER verwandt wurde.
sa_flags legt eine Gruppe von Schaltern fest, die das Verhalten des Signals verändern. Es wird durch bitweise ODER-Verknüpfung von Null oder mehreren der folgenden Werte erstellt:
Wenn der Schalter SA_SIGINFO in act.sa_flags angegeben wird, wird die Adresse des Signal-Handlers über das Feld act.sa_sigaction übergeben. Dieser Handler akzeptiert drei Argumente wie folgt:
void handler(int sig, siginfo_t *info, void *ucontext) {
... }
Die Bedeutung der drei Argumente im Einzelnen:
Der Datentyp siginfo_t ist eine Struktur mit den folgenden Feldern:
siginfo_t {
int si_signo; /* Signalnummer */
int si_errno; /* Ein Errno-Wert */
int si_code; /* Signal-Code */
int si_trapno; /* Ausnahmebehandlungsnummer die das Hardware-
gestüzte Signal hervorrief
(auf den meisten Architekturen unbenutzt) */
pid_t si_pid; /* Senden der Prozesskennung */
uid_t si_uid; /* Echte Benutzerkennung des sendenden Prozesses */
int si_status; /* Exit-Wert oder -Signal */
clock_t si_utime; /* Verbrauchte Benutzerzeit */
clock_t si_stime; /* Verbrauchte Systemzeit */
union sigval si_value; /* Signalwert */
int si_int; /* POSIX.1b-Signal */
void *si_ptr; /* POSIX.1b-Signal */
int si_overrun; /* Timer-Überlaufzähler;
POSIX.1b-Timer */
int si_timerid; /* Timer-Kennung; POSIX.1b-Timer */
void *si_addr; /* Speicherort, der die Ausnahmebehnadlung auslöste */
long si_band; /* Bandeereignis (war int in
Glibc 2.3.2 und älter) */
int si_fd; /* Dateideskriptor */
short si_addr_lsb; /* Niedrigstes Bit der Adresse
(seit Linux 2.6.32) */
void *si_lower; /* Untere Grenze bei Adresssverletzung
aufgetreten (seit Linux 3.19) */
void *si_upper; /* Obere Grenze bei Adresssverletzung
aufgetreten (seit Linux 3.19) */
int si_pkey; /* Schutzschlüssel auf PTE der die
Ausnahmebehandlung auslöste (seit Linux 4.6) */
void *si_call_addr; /* Adresse der Systemaufrufanweisung
(seit Linux 3.5) */
int si_syscall; /* Nummer des versuchten Systemaufrufs
(seit Linux 3.5) */
unsigned int si_arch; /* Architektur des versuchten Systemaufrufs
(seit Linux 3.5) */ }
si_signo, si_errno und si_code sind für alle Signale definiert. (si_errno ist im Allgemeinen unter Linux unbenutzt). Der Rest der Struktur kann eine Union sein, daher sollten nur die Felder ausgelesen werden, die für das übergebene Signal von Bedeutung sind:
Das Feld si_code innerhalb des an den Signal-Handler SA_SIGINFO übergebenen Arguments siginfo_t ist ein Wert (keine Bitmaske), der angibt, warum dieses Signal gesendet wurde. Für ein ptrace(2)-Ereignis wird si_code SIGTRAP enthalten und das Ptrace-Ereignis im hohen Byte enthalten.
(SIGTRAP | PTRACE_EVENT_foo << 8).
Für ein Ereignis außerhalb von ptrace(2) sind die Werte, die in si_code erscheinen können, im Rest dieses Abschnittes beschrieben. Seit Glibc 2.20 werden die Definitionen der meisten dieser Symbole aus <signal.h> erhalten, indem Feature-Test-Makros (vor dem Einbinden irgendeiner Header-Datei) wie folgt definiert werden:
Für die Konstanten TRAP_* werden die Symboldefinitionen nur in den ersten zwei Fällen bereitgestellt. Vor Glibc 2.20 wurde kein Feature-Test-Makro zum Erhalt dieser Symbole benötigt.
Für ein reguläres Signal zeigt die folgende Liste die Werte, die in si_code für jedes Signal gelegt werden können, zusammen mit dem Grund für die Erstellung des Signals.
Die folgenden Werte können in si_code für ein Signal SIGILL gesetzt werden:
Die folgenden Werte können in si_code für ein Signal SIGFPE gesetzt werden:
Die folgenden Werte können in si_code für ein Signal SIGSEGV gesetzt werden:
Die folgenden Werte können in si_code für ein Signal SIGBUS gesetzt werden:
Die folgenden Werte können in si_code für ein Signal SIGTRAP gesetzt werden:
Die folgenden Werte können in si_code für ein Signal SIGCHLD gesetzt werden:
Die folgenden Werte können in si_code für ein Signal SIGIOSIGPOLL gesetzt werden:
Die folgenden Werte können in si_code für ein Signal SIGSYS gesetzt werden:
Unter Linux akzeptiert der Aufruf sigaction() ohne Fehler unbekannte Bits, die in act->sa_flags gesetzt sind. Beginnend mit Linux 5.11 ist das Verhalten, dass ein zweiter Aufruf von sigaction() unbekannte Bits aus oldact->sa_flags bereinigen wird. Allerdings würde historisch ein zweiter Aufruf von sigaction() diese Bits in oldact->sa_flags gesetzt lassen.
Das bedeutet, dass die Unterstützung für neue Schalter nicht einfach dadurch erkannt werden kann, indem auf einen Schalter in sa_flags getestet wird und ein Programm muss testen, dass SA_UNSUPPORTED bereinigt wurde, beovr es sich auf die Inhalte von sa_flags verlassen kann.
Da das Verhalten des Signal-Handlers nicht garantiert werden kann, außer diese Prüfung war erfolgreich, ist es Weise, entweder das betroffene Signal zu blockieren, während der Handler registriert wird und in diesem Fall die Prüfung durchzuführen, oder, wo das nicht möglich ist, beispielsweise falls das Signal synchron ist, einen zweiten sigaction() im Signal-Handler selbst auszulösen.
Bei Kerneln, die einen bestimmten Schalter nicht unterstützen, verhält sich der Kernel so, als ob der Schalter nicht gesetzt worden wäre, selbst wenn der Schalter in act->sa_flags gesetzt wurde.
Die Schalter SA_NOCLDSTOP, SA_NOCLDWAIT, SA_SIGINFO, SA_ONSTACK, SA_RESTART, SA_NODEFER, SA_RESETHAND und, falls durch die Architektur definiert, SA_RESTORER können nicht zuverlässig mittels dieses Mechanismus erkannt werden, da sie vor Linux 5.11 eingeführt wurden. Allerdings können Programme im Allgemeinen annehmen, dass diese Schalter unterstüzt werden, da sie alle seit Linux 2.6, das im Jahr 2003 veröffentlicht wurde, unterstützt werden.
Siehe nachfolgende BEISPIELE für eine Vorstellung des Einsatzes von SA_UNSUPPORTED.
sigaction() gibt bei Erfolg Null zurück. Bei einem Fehler wird -1 zurückgegeben und errno entsprechend gesetzt.
POSIX.1-2001, POSIX.1-2008, SVr4.
Ein mittels fork(2) erstellter Kindprozess erbt eine Kopie der Signalzuordnungen seines Elternprozesses. Während eines execve(2) werden die Zuordnungen von verwalteten Signalen auf die Vorgabe zurückgesetzt; die Zuordnung ignorierter Signale werden unverändert gelassen.
Laut POSIX ist das Verhalten eines Prozesses undefiniert, nachdem er ein Signal SIGFPE, SIGILL oder SIGSEGV ignoriert hat, das nicht von kill(2) oder raise(3) erstellt wurde. Ganzzahldivision durch Null hat ein undefiniertes Ergebnis. Auf einigen Architekturen wird dies ein Signal SIGFPE hervorrufen. (Auch kann die Division der größten negativen Ganzzahl durch -1 SIGFPE hervorrufen.) Wird dieses Signal ignoriert, kann eine Endlosschleife auftreten.
POSIX.1-1990 verbot das Setzen der Aktion für SIGCHLD bis SIG_IGN. POSIX.1-2001 und neuer erlauben diese Möglichkeit, so dass das Ignorieren von SIGCHLD zur Vermeidung von Zombies verwandt werden kann (siehe wait(2)). Allerdings unterscheiden sich die historischen BSD- und System-V-Verhalten für das Ignorieren von SIGCHLD, so dass die einzige komplett portable Methode, um sicherzustellen, dass beendete Kinder nicht Zombies werden, das Fangen des Signals SIGCHLD und das Durchführen eines wait(2) oder ähnlichem ist.
POSIX.1-1990 spezifizierte nur SA_NOCLDSTOP. POSIX.1-2001 fügte SA_NOCLDSTOP, SA_NOCLDWAIT, SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_RESTART und SA_SIGINFO hinzu. Benutzung letzterer Werte in sa_flags könnte in Anwendungen, die für ältere UNIX-Implementierungen gedacht sind, weniger portabel sein.
Der Schalter SA_RESETHAND ist zu dem SVr4-Schalter mit dem gleichen Namen kompatibel.
Der Schalter SA_NODEFER ist mit dem SVr4-Schalter des gleichen Namens unter Kerneln 1.3.9 und neuer kompatibel. Unter älteren Kerneln erlaubte die Linux-Implementierung nicht das Empfangen irgendeines Signals, nicht nur desjenigen, das installiert wurde (was effektiv die Einstellungen sa_mask außer Kraft setzt).
Wird sigaction mit NULL als zweitem Argument aufgerufen, kann der augenblickliche Signal-Handler abgefragt werden. Die Funktion kann auch dazu benutzt werden, die Gültigkeit eines Signales für die aktuelle Maschine zu überprüfen, indem sie mit NULL als zweitem und drittem Argument aufgerufen wird.
Es ist nicht möglich, SIGKILL oder SIGSTOP zu blockieren (indem sie in sa_mask festgelegt werden). Derartige Versuche werden ohne Rückmeldung ignoriert.
Siehe sigsetops(3) für Details über das Bearbeiten von Signalgruppen.
Siehe signal-safety(7) für eine Liste der asynchron-signalsicheren Funktionen, die sicher innerhalb eines Signal-Handlers aufgerufen werden können.
Die Glibc-Wrapper-Funktion für sigaction() liefert bei Versuchen, die Zuordnung der zwei intern durch die NPTL-Threading-Implementierung verwandten Echtzeitsignale zu ändern, einen Fehler zurück. Siehe nptl(7) für Details.
Auf Architekturen, bei denen das Signal-Trampolin innerhalb der C-Bibliothek liegt, setzt die Glibc-Wrapper-Funktion für sigaction() die Adresse des Trampolin-Codes in das Feld act.sa_restorer und SA_RESTORER in das Feld act.sa_flags. Siehe sigreturn(2).
Der ursprüngliche Linux-Systemaufruf hieß sigaction(). Mit dem Hinzufügen von Echtzeitsignalen in Linux 2.2 passte der mit einer festen Größe versehene 32-Bit-Typ sigset_t nicht mehr für den Zweck. Daher wurde ein neuer Systemaufruf rt_sigaction() mit einem vergrößerten Typ sigset_t hinzugefügt. Der neue Systemaufruf akzeptiert ein viertes Argument size_t sigsetsize, das die Größe in Bytes der Signalgruppe in act.sa_mask und oldact.sa_mask festlegt. Dieses Argument muss derzeit den Wert sizeof(sigset_t) enthalten oder der Fehler EINVAL tritt auf. Die Glibc-Wrapper-Funktion sigaction() versteckt diese Details und ruft rt_sigaction() transparent auf, wenn der Kernel ihn bereitstellt.
Vor der Einführung von SA_SIGINFO war es auch möglich, einige zusätzliche Informationen über das Signal zu erhalten. Dies erfolgte durch Bereitstellung eines sa_handler-Signal-Handlers mit einem zweiten Argument des Typs struct sigcontext, das die gleiche Struktur ist, wie jene, die im Feld uc_mcontext der Struktur ucontext übergeben wird, die wiederum (mittels eines Zeigers) als drittes Argument des Handlers sa_sigaction übergeben wird. Siehe die relevanten Kernelquellen für Details. Diese Verwendung ist jetzt veraltet.
Wird ein Signal mit einem SA_SIGINFO-Handler ausgeliefert, stellt der Kernel nicht immer aussagekräftige Werte für alle Felder von siginfo_t, die relevant für dieses Signal sind, bereit.
In Linux bis einschließlich 2.6.13 verhinderte die Festlegung von SA_NODEFER in sa_flags nicht nur die Ausblendung des ausgelieferten Signals während der Ausführung des Handlers sondern auch der in sa_mask festgelegten Signale. Dieser Fehler wurde in Linux 2.6.14 behoben.
Siehe mprotect(2)
Das nachfolgende Beispielprogramm beendet sich mit dem Status EXIT_SUCCESS falls bestimmt wird, dass SA_EXPOSE_TAGBITS unterstützt wird, und andernfalls mit EXIT_FAILURE.
#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> 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); }
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)
Die deutsche Übersetzung dieser Handbuchseite wurde von René Tschirley <gremlin@cs.tu-berlin.de>, Martin Eberhard Schauer <Martin.E.Schauer@gmx.de> und Helge Kreutzmann <debian@helgefjell.de> erstellt.
Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.
Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Übersetzer.
10. Februar 2023 | Linux man-pages 6.03 |