Lisez attentivement signal(7) &pthread(7) &pthread_kill(3) &sigprocmask(2) &pthread_sigmask(3) - que vous pourriez utiliser (pour bloquer SIGINT
dans les threads indésirables). Lisez aussi un tutoriel pthread.
Évitez d'utiliser des signaux pour communiquer ou synchroniser entre les threads. Considérez par ex. mutex (pthread_mutex_lock etc...) et variables de condition (pthread_cond_wait etc...).
Si l'un des threads exécute une boucle d'événement (par exemple autour de poll(2)...), envisagez d'utiliser signalfd(2).
Si vous envoyez un signal à un processus, quel thread du processus gérera ce signal est indéterminé.
Selon pthread(7)
:
POSIX.1 exige également que les threads partagent une gamme d'autres attributs (c'est-à-dire que ces attributs sont à l'échelle du processus plutôt que par thread):
...
- disposition des signaux
...POSIX.1 distingue les notions de signaux dirigés vers le processus dans son ensemble et de signaux dirigés vers des threads individuels. Selon POSIX.1, un signal dirigé par un processus (envoyé en utilisant
kill(2)
, par exemple) doit être géré par un seul, arbitrairement thread sélectionné dans le processus.
Si vous souhaitez qu'un thread dédié dans votre processus traite certains signaux, voici un exemple de pthread_sigmask(3)
vous montre comment faire :
Le programme ci-dessous bloque certains signaux dans le thread principal, puis crée un thread dédié pour récupérer ces signaux via sigwait(3). La session shell suivante illustre son utilisation :
$ ./a.out &
[1] 5423
$ kill -QUIT %1
Signal handling thread got signal 3
$ kill -USR1 %1
Signal handling thread got signal 10
$ kill -TERM %1
[1]+ Terminated ./a.out
Origine du programme
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
/* Simple error handling functions */
#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void *
sig_thread(void *arg)
{
sigset_t *set = arg;
int s, sig;
for (;;) {
s = sigwait(set, &sig);
if (s != 0)
handle_error_en(s, "sigwait");
printf("Signal handling thread got signal %d\n", sig);
}
}
int
main(int argc, char *argv[])
{
pthread_t thread;
sigset_t set;
int s;
/* Block SIGQUIT and SIGUSR1; other threads created by main()
will inherit a copy of the signal mask. */
sigemptyset(&set);
sigaddset(&set, SIGQUIT);
sigaddset(&set, SIGUSR1);
s = pthread_sigmask(SIG_BLOCK, &set, NULL);
if (s != 0)
handle_error_en(s, "pthread_sigmask");
s = pthread_create(&thread, NULL, &sig_thread, (void *) &set);
if (s != 0)
handle_error_en(s, "pthread_create");
/* Main thread carries on to create other threads and/or do
other work */
pause(); /* Dummy pause so we can test program */
}