135 votes

Traitement du signal avec plusieurs threads sous Linux

Sous Linux, que se passe-t-il lorsqu'un programme (qui a éventuellement plusieurs threads) reçoit un signal, comme SIGTERM ou SIGHUP?

Quel thread intercepte le signal? Plusieurs threads peuvent-ils obtenir le même signal? Existe-t-il un fil spécial entièrement dédié à la gestion des signaux? Sinon, que se passe-t-il dans le thread qui doit gérer le signal? Comment l'exécution reprend-elle après la fin de la routine du gestionnaire de signal?

152voto

sarnold Points 62720

pthreads(7) explique que POSIX.1 exige que tous les threads d'un processus de partage d'attributs, y compris:

  • signal dispositions

POSIX.1 exige également certains attributs distincts pour chaque thread, y compris:

  • masque de signal (pthread_sigmask(3))

  • suppléant de signal de pile (sigaltstack(2))

Le noyau Linux est complete_signal() de routine a le bloc de code suivant -- les commentaires sont très utiles:

    /*
     * Now find a thread we can wake up to take the signal off the queue.
     *
     * If the main thread wants the signal, it gets first crack.
     * Probably the least surprising to the average bear.
     */
    if (wants_signal(sig, p))
            t = p;
    else if (!group || thread_group_empty(p))
            /*
             * There is just one thread and it does not need to be woken.
             * It will dequeue unblocked signals before it runs again.
             */
            return;
    else {
            /*
             * Otherwise try to find a suitable thread.
             */
            t = signal->curr_target;
            while (!wants_signal(sig, t)) {
                    t = next_thread(t);
                    if (t == signal->curr_target)
                            /*
                             * No thread needs to be woken.
                             * Any eligible threads will see
                             * the signal in the queue soon.
                             */
                            return;
            }
            signal->curr_target = t;
    }

    /*
     * Found a killable thread.  If the signal will be fatal,
     * then start taking the whole group down immediately.
     */
    if (sig_fatal(p, sig) &&
        !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
        !sigismember(&t->real_blocked, sig) &&
        (sig == SIGKILL || !t->ptrace)) {
            /*
             * This signal will be fatal to the whole group.
             */

Donc, vous voyez que vous êtes en charge de la où les signaux sont livrés:

Si votre processus a mis un signal de la disposition à l' SIG_IGN ou SIG_DFL, puis le signal est ignoré (ou par défaut -- tuer, de base, ou de l'ignorer) pour tous les threads.

Si votre processus a mis un signal de la disposition d'un gestionnaire spécifique de routine, alors vous pouvez contrôler le thread qui va recevoir les signaux en manipulant thread spécifique signal de masque à l'aide d' pthread_sigmask(3). Vous pouvez nommer un thread pour gérer tous les, ou de créer un thread par signal, ou tout mélange de ces options pour des signaux spécifiques, ou vous comptez sur le noyau Linux actuelles du comportement par défaut de la distribution du signal pour le thread principal.

Certains signaux, cependant, sont spéciaux:

   A signal may be generated (and thus pending) for a process as
   a whole (e.g., when sent using kill(2)) or for a specific
   thread (e.g., certain signals, such as SIGSEGV and SIGFPE,
   generated as a consequence of executing a specific machine-
   language instruction are thread directed, as are signals
   targeted at a specific thread using pthread_kill(3)).  A
   process-directed signal may be delivered to any one of the
   threads that does not currently have the signal blocked.  If
   more than one of the threads has the signal unblocked, then
   the kernel chooses an arbitrary thread to which to deliver
   the signal.

40voto

Alan Points 21367

C'est un peu nuancée, en fonction de la version du noyau Linux que vous utilisez.

En supposant 2.6 threads posix, et si l'on parle de l'OS de l'envoi de signal SIGTERM ou SIGHUP, le signal est envoyé, ce qui est reçue par et traitées par la racine fil. À l'aide de threads POSIX, vous pouvez également envoyé SIGTERM de threads individuels en tant que bien, mais je soupçonne que vous posez sur ce qui se passe lorsque le système d'exploitation envoie le signal au processus.

En 2.6, SIGTERM sera la cause de threads enfants à la sortie "propre", où, comme 2.4, threads enfants ont été laissés dans un état indéterminé.

3voto

Pavel Dudka Points 6059

En plus de la réponse d'Alan, voici un bon article simple sur la gestion des signaux sous Linux. http://www.alexonlinux.com/signal-handling-in-linux Amusez-vous!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X