sigaction(2) | System Calls Manual | sigaction(2) |
sigaction, rt_sigaction - Examiner et modifier l'action associée à un signal
Bibliothèque C standard (libc, -lc)
#include <signal.h>
int sigaction(int signum, const struct sigaction *_Nullable restrict act, struct sigaction *_Nullable restrict oldact);
sigaction() :
_POSIX_C_SOURCE
siginfo_t :
_POSIX_C_SOURCE >= 199309L
L'appel système sigaction() sert à modifier l'action effectuée par un processus à la réception d'un signal spécifique. (Consultez signal(7) pour une vue d'ensemble sur les signaux)
signum indique le signal concerné, à l'exception de SIGKILL et SIGSTOP.
Si act n'est pas NULL, la nouvelle action pour le signal signum est définie par act. Si oldact n'est pas NULL, l'ancienne action est sauvegardée dans oldact.
La structure sigaction est définie par quelque chose comme :
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };
Sur certaines architectures, on emploie une union. Il ne faut donc pas utiliser ou remplir simultanément sa_handler et sa_sigaction.
Le champ sa_restorer n'est pas conçu pour une utilisation dans une application (POSIX ne spécifie pas de champ sa_restorer). Vous pouvez trouver plus de détails sur l'objectif de ce champ dans sigreturn(2).
sa_handler indique l'action à associer à signum et il peut s'agir d'une des suivantes :
Si SA_SIGINFO est indiqué dans sa_flags, sa_sigaction (et non sa_handler) indique la fonction de gestion de signal dans signum. Cette fonction reçoit trois paramètres, comme décrit ci-dessous.
sa_mask spécifie un masque de signaux à bloquer (c'est-à-dire ajoutés au masque de signaux du thread dans lequel le gestionnaire est appelé) pendant l'exécution du gestionnaire. De plus le signal ayant appelé le gestionnaire est bloqué à moins que l'attribut SA_NODEFER soit précisé.
sa_flags spécifie un ensemble d'attributs qui modifient le comportement du signal. Il est formé par un OU binaire « | ») entre les options suivantes :
Quand le drapeau SA_SIGINFO est indiqué à act.sa_flags, l'adresse du gestionnaire de signal est passée à l'aide du champ act.sa_sigaction. Ce gestionnaire prend trois paramètres comme suit :
void handler(int sig, siginfo_t *info, void *ucontext) { ... }
Ces trois paramètres sont comme suit
Le type de données siginfo_t est une structure contenant les champs suivants :
siginfo_t { int si_signo; /* Numéro de signal */ int si_errno; /* Numéro d'erreur */ int si_code; /* Code du signal */ int si_trapno; /* Numéro de trappe qui a causé le signal généré par le matériel (pas utilisé sur la plupart des architectures) */ pid_t si_pid; /* PID de l'émetteur */ uid_t si_uid; /* UID réel de l'émetteur */ int si_status; /* Valeur de sortie ou signal */ clock_t si_utime; /* Temps utilisateur écoulé */ clock_t si_stime; /* Temps système écoulé */ union sigval si_value; /* Valeur du signal */ int si_int; /* Signal POSIX.1b */ void *si_ptr; /* Signal POSIX.1b */ int si_overrun; /* Décompte de dépassement des horloges (POSIX.1b) */ int si_timerid; /* ID d'horloge (POSIX.1b) */ void *si_addr; /* Emplacement mémoire ayant causé l'erreur */ long si_band; /* Band event (était int dans glibc 2.3.2 et antérieures */ int si_fd; /* Descripteur de fichier */ short si_addr_lsb; /* Bit le moins significatif de l'adresse (depuis Linux 2.6.32) */ void *si_lower; /* Limite inférieure lorsqu'une violation d'adresse se produit (depuis Linux 3.19) */ void *si_upper; /* Limite supérieure lorsqu'une violation d'adresse se produit (depuis Linux 3.19) */ int si_pkey; /* Clé de protection PTE à l'origine de l'ereur (depuis Linux 4.6) */ void *si_call_addr; /* Adresse de l'instruction d'appel système (depuis Linux 3.5) */ int si_syscall; /* Nombre d'appels système essayés (depuis Linux 3.5) */ unsigned int si_arch; /* Architecture des appels système essayés (depuis Linux 3.5) */ }
si_signo, si_errno et si_code sont définis pour tous les signaux (si_errno n'est généralement pas utilisé sous Linux). Le reste de la structure peut être une union, de telle sorte qu'on puisse ne lire que les champs spécifiques à un signal donné :
Le champ si_code du paramètre siginfo_t passé à un gestionnaire de signal SA_SIGINFO est une valeur (et non un masque de bit) indiquant la raison de l'envoi de ce signal. Pour un événement ptrace(2), si_code contiendra SIGTRAP et aura l'événement ptrace dans l'octet fort :
(SIGTRAP | PTRACE_EVENT_foo << 8).
Pour un événement non ptrace(2), les valeurs qui peuvent apparaître dans si_code sont décrites dans le reste de cette section. Depuis la glibc 2.20, les définitions de la plupart de ces symboles viennent de <signal.h> en définissant des macros de test de fonctionnalités (avant l'inclusion de tout fichier d'en-tête) comme suit :
Pour les constantes TRAP_*, les définitions de symboles ne sont fournies que dans les deux premiers cas. Avant la glibc 2.20, aucune macro de test n'était nécessaire pour obtenir ces symboles.
Pour un signal normal, la liste suivante indique les valeurs que peut prendre si_code pour n'importe quel signal, avec la raison associée.
Les valeurs suivantes peuvent être prises par si_code pour un signal SIGILL :
Les valeurs suivantes peuvent être prises par si_code pour un signal SIGFPE :
Les valeurs suivantes peuvent être prises par si_code pour un signal SIGSEGV :
Les valeurs suivantes peuvent être prises par si_code pour un signal SIGBUS :
Les valeurs suivantes peuvent être prises par si_code pour un signal SIGTRAP :
Les valeurs suivantes peuvent être prises par si_code pour un signal SIGCHLD :
Les valeurs suivantes peuvent être prises par si_code pour un signal SIGIO/SIGPOLL :
Les valeurs suivantes peuvent être prises par si_code pour un signal SIGSYS :
L'appel sigaction() sur Linux accepte des jeux de bits inconnus act->sa_flags sans erreur. Le comportement du noyau, à partir de Linux 5.11, est qu'un deuxième sigaction(2) videra les bits inconnus de oldact->sa_flags. Toutefois, historiquement, un second appel sigaction() laissait généralement ces ensembles de bits dans oldact->sa_flags.
Cela signifie que la prise en charge de nouveaux drapeaux ne peut pas être détectée par un simple test du drapeau sa_flags dans sa_flags et un programme doit tester que SA_UNSUPPORTED a été vidé avant de s'appuyer sur le contenu de sa_flags.
Comme le comportement du gestionnaire ne peut pas être garanti, sauf si la vérification réussit, il vaut mieux soit bloquer le signal concerné tout en enregistrant le gestionnaire puis effectuer la vérification dans ce cas, soit, quand cela n'est pas possible, par exemple si le signal est synchrone, effectuer le deuxième sigaction() dans le gestionnaire de signal lui-même.
Dans les noyaux qui ne prennent pas en charge un drapeau en particulier, le comportement du noyau est le même que si le drapeau n'était pas positionné, même si ce dernier a été positionné avec act->sa_flags.
Les drapeaux SA_NOCLDSTOP, SA_NOCLDWAIT, SA_SIGINFO, SA_ONSTACK, SA_RESTART, SA_NODEFER, SA_RESETHAND et, s'il est défini par l'architecture, SA_RESTORER, peuvent ne pas être sondés de manière fiable si on utilise ce mécanisme, parce qu'ils ont été introduits avant Linux 5.11. Cependant, en général, les programmes peuvent supposer que ces drapeaux sont pris en charge car ils le sont depuis Linux 2.6, publié en 2003.
Consultez les EXEMPLES ci-dessous pour une démonstration de l'utilisation de SA_UNSUPPORTED.
sigaction() renvoie 0 s'il réussit. En cas d'erreur, -1 est renvoyé et errno contient le code d'erreur.
POSIX.1-2001, POSIX.1-2008, SVr4.
Un enfant créé par fork(2) hérite d'une copie des actions des signaux de son parent. Lors d'un execve(2), les actions des signaux pris en charge sont remises aux valeurs par défaut ; les actions des signaux ignorés ne sont pas modifiées.
Comme spécifié par POSIX, le comportement d'un processus est indéfini après la réception d'un signal SIGFPE, SIGILL, ou SIGSEGV qui n'a pas été engendré par une fonction kill(2) ou raise(3). La division entière par zéro a un résultat indéfini, sur certaines architectures elle déclenche un signal SIGFPE. De même, diviser l'entier le plus négatif par -1 peut déclencher SIGFPE.
POSIX.1-1990 interdisait de positionner SIGCHLD avec SIG_IGN. POSIX.1-2001 l'autorise, et ignorer SIGCHLD permet donc d'éviter la création de zombies (consultez wait(2)). Cependant, les comportements historiques de BSD et de System V quand SIGCHLD est ignoré diffèrent, si bien que la seule méthode complètement portable pour s'assurer que les enfants ne deviennent pas des zombies à leur terminaison est d'intercepter le signal SIGCHLD et d'invoquer wait(2) ou équivalent.
POSIX.1-1990 ne documentait que SA_NOCLDSTOP. POSIX.1-2001 a ajouté SA_NOCLDWAIT, SA_RESETHAND, SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_RESTART et SA_SIGINFO. L'utilisation de ces dernières valeurs dans sa_flags peut être moins portable dans les applications censées s'exécuter sur des implémentations UNIX anciennes.
L'option SA_RESETHAND est compatible avec l'option SVr4 du même nom.
Le drapeau SA_NODEFER est compatible avec le drapeau SVr4 du même nom pour les noyaux 1.3.9 et ultérieurs. Pour les noyaux plus anciens, Linux autorisera la réception de tous les signaux et pas seulement celui qu'on est en train de mettre en place (écrasant de fait sa_mask).
sigaction() peut être appelé avec un second argument NULL pour obtenir le gestionnaire de signaux actuel. On peut aussi vérifier si un signal est valide sur la machine actuelle en l'appelant avec les deuxième et troisième arguments qui valent NULL.
Il est impossible de bloquer SIGKILL or SIGSTOP (en les indiquant dans sa_mask). Les tentatives seront ignorées silencieusement.
Consultez sigsetops(3) pour les détails concernant les ensembles de signaux.
Consultez signal-safety(7) pour une liste de fonctions sûres pour les signaux asynchrones qui peuvent être appelées dans un gestionnaire de signal.
La fonction enveloppe de la glibc autour de sigacttion() donne une erreur (EINVAL) lorsqu'on essaie de changer la position des deux signaux en temps réel utilisés en interne par l'implémentation de threading de NPTL. Consultez nptl(7) pour plus de détails.
Sur des architectures où le trampoline du signal se trouve dans la bibliothèque C, la fonction enveloppe de la bibliothèque C autour de sigaction() met l'adresse du code de trampoline dans le champ act.sa_restorer et positionne le drapeau SA_RESTORER du champ act.sa_flags. Consultez sigreturn(2).
L'appel système Linux d'origine s'appelait sigaction(). Toutefois, avec l'arrivée des signaux en temps réel dans Linux 2.2 et de la taille figée, le type sigset_t 32 bits pris en charge par cet appel système ne convenait plus à cet objectif. Par conséquent, un nouvel appel système rt_sigaction() a été ajouté pour prendre en charge le type sigset_t élargi. Le nouvel appel système prend un quatrième paramètre, size_t sigsetsize, qui indique la taille en octets des jeux de signal dans act.sa_mask et oldact.sa_mask. Ce paramètre est actuellement nécessaire pour obtenir la valeur sizeof(sigset_t) (ou le résultat de l'erreur EINVAL). La fonction enveloppe sigaction() de la glibc nous cache ces détails en appelant de manière transparente rt_sigaction() quand le noyau le fournit.
Avant l'introduction de l'attribut SA_SIGINFO il était déjà possible d'obtenir des informations supplémentaires sur un signal. Cela se faisait en fournissant au gestionnaire de signal sa_handler un second paramètre de type struct sigcontext, qui est la même structure que celle fournie dans le champ uc_mcontext de la structure ucontext passée (à l'aide d'un pointeur) comme troisième paramètre du gestionnaire sa_sigaction Consultez les sources du noyau Linux pertinentes pour des détails. Cette utilisation est désormais obsolète.
Au moment où un signal est délivré avec le gestionnaire SA_SIGINFO, le noyau ne fournit pas toujours des valeurs significatives pour tous les champs de siginfo_t cohérentes pour ce signal.
Jusqu'à Linux 2.6.13 inclus, indiquer SA_NODEFER dans sa_flags empêchait non seulement le signal reçu d'être masqué pendant l'exécution du gestionnaire, mais empêchait également les signaux de sa_mask d'être masqués. Ce bogue a été corrigé dans Linux 2.6.14.
Consultez mprotect(2).
Le programme d'exemple suivant quitte avec l'état EXIT_SUCCESS si SA_EXPOSE_TAGBITS a vocation à être pris en charge, ou sinon 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)
La traduction française de cette page de manuel a été créée par Christophe Blaess <https://www.blaess.fr/christophe/>, Stéphan Rafin <stephan.rafin@laposte.net>, Thierry Vignaud <tvignaud@mandriva.com>, François Micaux, Alain Portal <aportal@univ-montp2.fr>, Jean-Philippe Guérard <fevrier@tigreraye.org>, Jean-Luc Coulon (f5ibh) <jean-luc.coulon@wanadoo.fr>, Julien Cristau <jcristau@debian.org>, Thomas Huriaux <thomas.huriaux@gmail.com>, Nicolas François <nicolas.francois@centraliens.net>, Florentin Duneau <fduneau@gmail.com>, Simon Paillard <simon.paillard@resel.enst-bretagne.fr>, Denis Barbier <barbier@debian.org>, David Prévot <david@tilapin.org>, Cédric Boutillier <cedric.boutillier@gmail.com>, Frédéric Hantrais <fhantrais@gmail.com> et Jean-Philippe MENGUAL <jpmengual@debian.org>
Cette traduction est une documentation libre ; veuillez vous reporter à la GNU General Public License version 3 concernant les conditions de copie et de distribution. Il n'y a aucune RESPONSABILITÉ LÉGALE.
Si vous découvrez un bogue dans la traduction de cette page de manuel, veuillez envoyer un message à debian-l10n-french@lists.debian.org.
10 février 2023 | Pages du manuel de Linux 6.03 |