Si vous générez le SIGINT
avec Ctrl +C sur un système Unix, le signal est envoyé à l'ensemble du groupe de processus.
Vous devez utiliser setpgid ou setsid pour placer le processus enfant dans un groupe de processus différent afin qu'il ne reçoive pas les signaux générés par le terminal de contrôle.
[Modifier :]
Assurez-vous de lire la section JUSTIFICATION du setpgid
soigneusement la page. Il est un peu difficile de brancher toutes les conditions de course potentielles ici.
Pour garantir à 100 % qu'aucun SIGINT
sera livré à votre processus enfant, vous devez faire quelque chose comme ceci :
#define CHECK(x) if(!(x)) { perror(#x " failed"); abort(); /* or whatever */ }
/* Block SIGINT. */
sigset_t mask, omask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
CHECK(sigprocmask(SIG_BLOCK, &mask, &omask) == 0);
/* Spawn child. */
pid_t child_pid = fork();
CHECK(child_pid >= 0);
if (child_pid == 0) {
/* Child */
CHECK(setpgid(0, 0) == 0);
execl(...);
abort();
}
/* Parent */
if (setpgid(child_pid, child_pid) < 0 && errno != EACCES)
abort(); /* or whatever */
/* Unblock SIGINT */
CHECK(sigprocmask(SIG_SETMASK, &omask, NULL) == 0);
Strictement parlant, chacune de ces étapes est nécessaire. Vous devez bloquer le signal au cas où l'utilisateur appuie sur Ctrl +C juste après l'appel au fork
. Vous devez appeler le setpgid
chez l'enfant au cas où le execl
survient avant que le parent ait eu le temps de faire quoi que ce soit. Vous devez appeler le setpgid
dans le parent au cas où le parent s'exécute et quelqu'un appuie sur Ctrl +C devant l'enfant a le temps de faire n'importe quoi.
La séquence ci-dessus est maladroite, mais elle gère 100 % des conditions de course.