Question

J'écris un programme essentiel au système pour une distribution Linux que je développe. Il doit redémarrer à la réception de certains signaux pour éviter un crash. Le problème est que, après le redémarrage, je ne peux pas réactiver ce signal. Autrement dit, le signal ne peut pas être reçu deux fois. Après execv (), lorsque le nouveau processus appelle signal () pour configurer le signal, SIG_DFL est renvoyé. À chaque fois. Même si je l’appelle deux fois de suite, cela signifie qu’il n’a jamais été réglé. Un drapeau étrange est-il reporté du processus d'origine?

Était-ce utile?

La solution

Vous craignez le fait que vous essayez essentiellement de gérer un signal de manière récursive.

Lorsque vous utilisez signal() pour enregistrer un gestionnaire de signaux, ce numéro de signal est bloqué jusqu'au retour du gestionnaire de signaux. En fait, le noyau / libc bloque ce numéro de signal lorsque le gestionnaire de signaux est appelé et le débloque après son retour. . Comme vous ne revenez jamais du gestionnaire de signal (à la place vous execl un nouveau binaire), SIGUSR1 reste bloqué et n'est donc pas intercepté une seconde fois.

Ceci peut être constaté en examinant /proc/</pid>/status avant et après l'envoi du premier SigCgt.

Avant:

$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000000
SigCgt: 0000000000000200

Après:

$ cat /proc/<pid>/status | grep -E "Sig(Cgt|Blk)"
SigBlk: 0000000000000200
SigCgt: 0000000000000200

Notez que man signal(7) indique que le signal 10 est enregistré (le numéro est un champ de bits; le 10ème bit est défini, ce qui équivaut à SIGUSR1, voir SigBlk pour les numéros). SIGUSR est vide avant que sighandler soit envoyé à votre processus, mais après l'envoi du signal, il contient sigaction.

Vous avez deux moyens de résoudre ce problème:

a). Débloquer manuellement SA_NODEFER avant d'appeler signal dans <=>:

sigset_t sigs;
sigprocmask(0, 0, &sigs);
sigdelset(&sigs, SIGUSR1);
sigprocmask(SIG_SETMASK, &sigs);

b). Utilisez <=> avec l'indicateur <=> au lieu de <=> pour enregistrer le gestionnaire de signaux. Ceci évitera le blocage de <=> l'intérieur du gestionnaire de signaux:

struct sigaction act;
act.sa_handler = signalhandler;
act.sa_mask = 0;
act.sa_flags = SA_NODEFER;
sigaction(SIGUSR1, &act, 0);

Autres conseils

Les gestionnaires de signaux ne sont pas hérités sur exec parce que SIG_IGN écrase tout votre espace adresse et que tous les gestionnaires de signaux non réinitialisés pointeraient alors au mauvais endroit. La seule fois où il n'est pas réinitialisé, c'est s'il est défini sur, par exemple, <=>, ce qui ne dépend pas de l'espace d'adressage du processus précédent - <=>.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top