SIGNAL |
Signal |
---|---|
Langage C++ | csignal (signal.h) |
Syntaxe
void (*signal(int signal,void (*shandle)(int)))(int) |
Paramètres
Nom | Description |
---|---|
signal | Ce paramètre permet d'indiquer le code de signal |
shandle | Ce paramètre permet d'indiquer l'identificateur de signal |
Description
Cette fonction permet d'effectuer un traitement de signal.
Remarques
- La fonction signal() enregistre la fonction pointée par shandle comme gestionnaire du signal spécifié par signal. Autrement dit, la fonction pointée par shandle sera appelée lorsque le signal sera reçu par votre programme.
- La valeur de shandle peut être l'adresse d'une fonction de gestionnaire de signal ou l'une des macros suivantes, définies dans «csignal» :
Nom Description SIG_DFL Cette macro permet d'indiquer qu'il faut utiliser la gestion du signal par défaut. SIG_IGN Cette macro permet d'indiquer qu'il faut ignorer le signal. Si une adresse de fonction est utilisée, le gestionnaire spécifié sera exécuté lorsque son signal sera reçu.
- En cas de succès, la fonction signal() renvoie l'adresse de la fonction précédemment définie pour le signal spécifié. En cas d'erreur, SIG_ERR (défini dans «csignal») est renvoyé.
- Définition et utilité : La fonction signal est utilisée pour définir un gestionnaire de signal personnalisé pour un processus en cours d'exécution. Elle permet de modifier le comportement par défaut lorsqu'un signal spécifique est reçu, comme l'arrêt du programme (SIGINT), une erreur de segmentation (SIGSEGV), ou une division par zéro (SIGFPE).
- Types de gestionnaires possibles : La fonction signal accepte trois types de gestionnaires : Un pointeur vers une fonction étant appelée lors de la réception du signal. SIG_DFL (valeur par défaut) pour rétablir le comportement standard du signal. SIG_IGN pour ignorer complètement le signal. Exemple :
- Ne fonctionne pas toujours bien avec les processus légers : signal est principalement conçu pour un environnement mono-processus léger. Dans un programme multi-processus léger, la gestion des signaux peut être imprévisible, car les signaux peuvent être reçus par n'importe quel processus léger du processus. Il est généralement recommandé d'utiliser sigaction au lieu de signal pour une gestion plus robuste des signaux dans les applications multi-processus léger.
- Certains signaux ne peuvent pas être capturés ou ignorés : Certains signaux ne peuvent pas être capturés, redirigés ou ignorés, comme SIGKILL et SIGSTOP.
- SIGKILL force l'arrêt immédiat du programme sans possibilité de récupération. SIGSTOP met le processus en pause et ne peut être ignoré. Par conséquent, toute tentative d'utiliser signal(SIGKILL, handler) ne fonctionnera pas.
- Effet sur le comportement par défaut du programme : En définissant un gestionnaire avec signal, on remplace le comportement standard du programme.
- Par exemple, SIGINT (généré par Ctrl+C) termine normalement le programme, mais un gestionnaire peut modifier ce comportement pour afficher un message ou enregistrer des données avant la fermeture. Attention cependant : intercepter certains signaux sans précaution peut empêcher un programme de se fermer normalement et le rendre difficile à arrêter.
- Risques de conditions de concurrence et d'accès concurrent aux variables globales : Lorsqu'un signal est capté, la fonction de gestion (handler) s'exécute immédiatement, interrompant potentiellement le programme en plein traitement.
- Si le gestionnaire modifie une variable globale, il faut faire attention aux conditions de course. L'utilisation de volatile sig_atomic_t est recommandée pour éviter les incohérences des données. Exemple :
- Alternatives modernes avec sigaction : signal est une vieille API, et son comportement varie selon les plateformes. Une alternative plus robuste et portable est sigaction, offrant : Une meilleure gestion des signaux en définissant des masques pour bloquer d'autres signaux pendant l'exécution du gestionnaire. Une gestion plus prévisible des signaux dans les applications multi-processus léger. Exemple avec sigaction :
- #include <csignal>
- #include <iostream>
- void handleSignal(int signum) {
- std::cout << "Signal capturé avec sigaction : " << signum << std::endl;
- }
- int main() {
- struct sigaction sa;
- sa.sa_handler = handleSignal;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction(SIGINT, &sa, NULL);
- while (true); // Attente d'un signal
- }
- Exemple d'application pratique : gestion des erreurs et sauvegarde avant sortie, signal peut être utilisé pour gérer proprement une erreur et effectuer des opérations avant que le programme ne se termine : Sauvegarde des données, libération de la mémoire, fermeture des fichiers ouverts. Exemple :
Ici, le programme affiche un message lorsqu'il reçoit SIGINT (Ctrl+C).
Cette technique garantit que signalReceived est correctement mis à jour même en cas d'interruption soudaine.
sigaction offre une meilleure fiabilité que signal dans les programmes complexes.
Ici, le programme intercepte SIGTERM (généré par kill sous Linux) et sauvegarde les données avant de quitter proprement.
Voir également
Langage de programmation - C++ - Référence de procédures et fonctions - abort
Langage de programmation - C++ - Référence de procédures et fonctions - exit
Langage de programmation - C++ - Référence de procédures et fonctions - longjmp
Langage de programmation - C++ - Référence de procédures et fonctions - raise
Langage de programmation - C++ - Référence de procédures et fonctions - setjmp
Langage de programmation - C - Référence de procédures et fonctions - signal
Références
Langage C, Edition Micro-Application, Gehard Willms, 2001, ISBN: 2-7429-2008-0, page 734.
Borland C++ for Windows 4.0, Library Reference, Edition Borland, 1993, Part # BCP1240WW21772, page 237.