Le comportement des signaux classiques d'UNIX est malheureusement différent d'une version à l'autre. On emploie donc de préférence les mécanismes définis par la norme POSIX, qui offrent de plus la possibilité de masquer des signaux.
Le type sigset_t
représente les ensembles de signaux.
#include <signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
La fonction sigemptyset()
crée un ensemble vide,
sigaddset()
ajoute un élément, etc.
sigaction()
#include <signal.h>
int sigaction(int signum,
const struct sigaction *act,
struct sigaction *oldact);
La fonction sigaction()
change l'action qui sera
exécutée lors de la réception d'un signal. Cette action
est décrite par une structure struct sigaction
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void); /* non utilisé */
}
sa_handler
indique l'action associée au signal
signum
. Il peut valoir
SIG_DFL
(action par défaut),
SIG_IGN
(ignorer),
ou un pointeur vers une fonction de traitement de lu signal.
sa_mask
indique l'ensemble de signaux qui seront bloqués
pendant l'exécution de ce signal. Le signal lui-même sera bloqué, sauf
si SA_NODEFER
ou SA_NOMASK
figurent parmi les flags.Le champ sa_flags
contient une combinaison d'indicateurs,
parmi lesquels
SA_NOCLDSTOP
pour le signal SIGCHLD
, ne pas
recevoir la notification d'arrêt des processus fils
(quand les processus fils reçoivent
SIGSTOP
,
SIGTSTP
, SIGTTIN
ou SIGTTOU
).
SA_ONESHOT
ou SA_RESETHAND
remet l'action par défaut quand le handler a été appelé
(c'est le comportement par défaut du signal()
classique).
SA_SIGINFO
indique qu'il faut utiliser la fonction
sa_sigaction()
à trois paramètres à la place de
sa_handler()
.Exemple :
1 /* sig-posix.c */
2 #include <stdlib.h>
3 #include <signal.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <stdio.h>
7 #define DELAI 1
8 #define NBTOURS 60
9 void traitement(int signum)
10 {
11 struct sigaction rien, ancien;
12 printf("Signal %d => ", signum);
13 switch (signum) {
14 case SIGTSTP:
15 printf("J'ai reçu un SIGTSTP.\n");
16 /* on désarme le signal SIGTSTP */
17 rien.sa_handler = SIG_DFL;
18 rien.sa_flags = 0;
19 sigemptyset(&rien.sa_mask); /* rien à masquer */
20 sigaction(SIGTSTP, &rien, &ancien);
21 printf("Alors je m'endors....\n");
22 kill(getpid(), SIGSTOP); /* auto-endormissement */
23 printf("On me réveille ?\n");
24 /* remise en route */
25 sigaction(SIGTSTP, &ancien, NULL);
26 printf("C'est reparti !\n");
27 break;
28 case SIGINT:
29 case SIGTERM:
30 printf("On m'a demandé d'arrêter le programme.\n");
31 exit(EXIT_SUCCESS);
32 break;
33 };
34 }
35 int main(void)
36 {
37 struct sigaction a;
38 int i;
39 a.sa_handler = traitement; /* fonction à lancer */
40 sigemptyset(&a.sa_mask); /* rien à masquer */
41 sigaction(SIGTSTP, &a, NULL); /* pause contrôle-Z */
42 sigaction(SIGINT, &a, NULL); /* fin contrôle-C */
43 sigaction(SIGTERM, &a, NULL); /* arrêt */
44 for (i = 1; i < NBTOURS; i++) {
45 sleep(DELAI);
46 printf("%d", i % 10);
47 fflush(stdout);
48 };
49 printf("Fin\n");
50 exit(EXIT_SUCCESS);
51 }