Outre le problème du «trop de signaux», les signaux peuvent être explicitement ignorés. De man 2 signal
:
If the signal signum is delivered to the process, then one of the
following happens:
* If the disposition is set to SIG_IGN, then the signal is ignored.
Les signaux peuvent également être bloqués. De man 7 signal
;
A signal may be blocked, which means that it will not be delivered
until it is later unblocked. Between the time when it is generated
and when it is delivered a signal is said to be pending.
Les ensembles de signaux bloqués et ignorés sont hérités par les processus enfants, il peut donc arriver que le processus parent de votre application ait ignoré ou bloqué l'un de ces signaux.
Que se passe-t-il lorsque plusieurs signaux sont délivrés avant que le processus ait fini de traiter les précédents? Cela dépend du système d'exploitation. La signal(2)
page de manuel liée ci-dessus en parle:
- Le système V réinitialisera la disposition du signal par défaut. Pire, la livraison rapide de plusieurs signaux entraînerait des appels récursifs (?).
- BSD bloquerait automatiquement le signal jusqu'à ce que le gestionnaire ait terminé.
- Sous Linux, cela dépend des indicateurs de compilation définis pour GNU
libc
, mais je m'attendrais à ce que le comportement BSD.
signal(2)
suggère catégoriquement d'éviter cette confusion en utilisant à lasigaction(2)
place.Vous ne pouvez pas croire que chaque signal envoyé sera délivré. Par exemple, le noyau linux "fusionne" SIGCHLD si un processus met longtemps à gérer SIGCHLD à partir d'un processus enfant quitté.
Pour répondre à une autre partie de votre question, les signaux sont "mis en file d'attente" à l'intérieur du noyau si un certain nombre de signaux différents arrivent dans un intervalle trop court.
Vous devez utiliser
sigaction()
pour configurer le gestionnaire de signal avec lesa_sigaction
membre desiginfo_t
, en définissant soigneusement lesa_mask
membre de l'siginfo_t
argument. Je pense que cela signifie masquer tous les signaux "asynchrone" au moins. Selon la page de manuel pour Linuxsigaction()
, vous masquerez également le signal traité. Je pense que vous devriez définir lesa_flags
membre sur SA_SIGINFO, mais je ne me souviens pas pourquoi j'ai cette superstition. Je crois que cela donnera à votre processus un gestionnaire de signaux qui reste défini sans conditions de concurrence et qui ne sera pas interrompu par la plupart des autres signaux.Écrivez votre fonction de gestionnaire de signaux très, très soigneusement. Fondamentalement, il suffit de définir une variable globale pour indiquer qu'un signal a été capturé et que le reste du processus gère l'action souhaitée pour ce signal. Les signaux seront masqués pendant le moins de temps possible.
De plus, vous voudrez tester votre code de gestion du signal de manière très approfondie. Mettez-le dans un petit processus de test et envoyez autant de signaux SIGUSR1 et SIGUSR2 que possible, peut-être à partir de 2 ou 3 programmes d'envoi de signaux spéciaux. Mélangez également d'autres signaux, une fois que vous êtes sûr que votre code peut gérer SIGUSR1 et SIGUSR2 rapidement et correctement. Préparez-vous à un débogage difficile.
Si vous utilisez Linux et uniquement Linux, vous pourriez penser à utiliser
signalfd()
pour créer un descripteur de fichier que vous pouvezselect()
interroger pour recevoir ces signaux. L'utilisationsignalfd()
pourrait faciliter le débogage.la source
Un signal est garanti d'être délivré, dans le sens où si un processus appelle avec succès
kill
, alors la cible recevra le signal. C'est asynchrone: l'expéditeur n'a aucun moyen de savoir quand le signal est reçu ou traité. Cependant, cela ne garantit pas que le signal sera délivré. La cible pourrait mourir avant de pouvoir traiter le signal. Si la cible ignore le signal au moment où il est délivré, le signal n'aura aucun effet. Si la cible reçoit plusieurs instances du même numéro de signal avant de pouvoir les traiter, les signaux peuvent (et sont généralement) fusionnés: si vous envoyez deux fois le même signal à un processus, vous ne pouvez pas savoir si le processus recevra le signal. une fois ou deux. Les signaux sont principalement conçus pour tuer un processus ou pour faire attention à un processus, ils ne sont pas conçus pour la communication en tant que tels.Si vous avez besoin d'une livraison fiable, vous avez besoin d'un mécanisme de communication différent. Il existe deux principaux mécanismes de communication entre les processus: un tuyau permet une communication unidirectionnelle; un socket permet une communication bidirectionnelle et plusieurs connexions au même serveur. Si vous avez besoin de la cible pour traiter autant de notifications que vous l'envoyez, envoyez des octets sur un canal.
la source
Le noyau est libre de fusionner les signaux standard si plus d'un est délivré alors qu'il est bloqué. Les signaux en temps réel, en revanche, ne sont pas pareillement handicapés.
Depuis la page de manuel signal (7) :
Essayez d'utiliser un signal avec un nombre compris entre SIGRTMIN et SIGRTMAX.
la source
ulimit -i
affiche cette valeur comme 63432 sur Ubuntu 18.04.