IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

POSIX C Discussion :

Fin de programme propre après interception de SIGINT


Sujet :

POSIX C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 22
    Par défaut Fin de programme propre après interception de SIGINT
    Bonjour,

    Je me demandais comment traiter proprement une fin de programme lors de l'interception d'un signal SIGINT par un gestionnaire de signaux. Prenons un programme réalisant deux allocations mémoire puis qui boucle sur un while(1) ; Lors de la réception du signal SIGINT une fonction void handler(int) ; est appelée. Comment faire pour que le programme libère la mémoire allouée avant de quitter avec un appel à la fonction exit ? Faut-il utiliser des variables globales pour connaître les adresses des pointeurs à libérer ?

    Je cherche la manière la plus propre de faire mais je ne vois pas trop. J'ai également déjà lu qu'on devait mettre le moins de code possible dans le handler ce qui à priori dans ma méthode n'est pas le cas. Voilà, donc comment faire ? Je m'en remet à vos connaissances.

    Quoiqu'il en soit merci d'avance pour vos conseils.

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Salut

    Si tu quittes ton programme, la mémoire allouée avec malloc() est libérée automatiquement..... puisque le programme et son espace mémoire n'existent plus ^^ Je pense que tu n'as pas besoin de t'embêter avec ça : tu termines ton programme, c'est tout.

    En revanche, tu peux avoir d'autres ressources à libérer : connexion ouverte à une base de donnée, fichier ouvert, etc.

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Juste pour préciser, sur certains systèmes très anciens, ou très particulier, la mémoire allouée par un malloc() n'est pas libérée automatiquement à la mort d'un programme.

    Mais si c'était ton cas, tu le saurais.

  4. #4
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 22
    Par défaut
    Merci pour vos réponses.
    Je sais en effet que sur les systèmes récents la mémoire est libérée automatiquement mais comme tu le dis il peut s'agir de fermer des descripteurs de fichiers ou autre. Mon exemple était peut-être mal choisi mais j'ai voulu faire simple et le problème reste le même : comment fermer ou libérer la mémoire de manière propre à l'interception d'un SIGINT ?

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 486
    Par défaut
    Bonjour,

    Citation Envoyé par Dliw0 Voir le message
    Je sais en effet que sur les systèmes récents la mémoire est libérée automatiquement mais comme tu le dis il peut s'agir de fermer des descripteurs de fichiers ou autre. Mon exemple était peut-être mal choisi mais j'ai voulu faire simple et le problème reste le même : comment fermer ou libérer la mémoire de manière propre à l'interception d'un SIGINT ?
    C'est une question pertinente car c'est un problème de conception initiale, qui devrait occuper tous les développeurs dès les premières lignes de leur programme. En gros, il faut écrire ton programme tel que tu le ferais si c'était le système d'exploitation lui-même que tu écrivais.

    D'une manière générale, on essaie d'éviter de recourir aux variables globales pour un certain nombre de raisons, mais c'est effectivement typiquement dans ce genre de cas qu'on va les trouver. En fait, on va surtout utiliser une fonction qui ne conservera qu'un pointeur dans une variable statique et qui nous enverra son contenu sur demande, pointeur vers une structure dont l'espace est alloué avec un malloc et qui, elle, va contenir toutes les infos que l'on a besoin de partager.

    Mais la manière la plus propre, dans ce cas précis, de gérer la chose reste de n'en faire toujours que le minimum dans les handlers de signaux, qui doivent rendre la main le plus vite possible. La bonne réponse, dans ton cas, consiste donc à faire en sorte que ton gestionnaire de signal place un flag quelque part, qui soit interprété ensuite comme une demande de sortie ordinaire par ton programme. Ainsi, tu es sûr que le workflow de ton programme ira quand même jusqu'à son terme, ce qui est le meilleur moyen de ne rien oublier.

    Tu peux également utiliser atexit() pour appeler des fonctions de nettoyage dès que ton programme se termine. Attention : c'est valable pour les sorties en conditions normales avec exit() ou lorsque que l'on sort de main(), mais pas sur _exit() ou lorsque tu reçois un signal tueur non pris en charge. En revanche, tu peux invoquer plusieurs fois cette fonction, ce qui te permet de la placer partout où tu fais des allocations. Par contre, à terme, il vaut mieux s'en passer et écrire un programme qui soit naturellement conçu pour passer par les phases de sortie.

    À noter enfin qu'il faut également prendre en compte la sémantique des signaux eux-mêmes (pas toujours très claire, d'ailleurs) : SIGINT demande au programme de s'interrompre et SIGTERM de prendre fin normalement. Ça veut dire que dans le premier cas, on ne souhaite pas nécessairement mener à terme l'opération en cours (ce qui ne veut pas dire qu'il ne faut pas sortir proprement). Dans le second, on termine ce que l'on est en train de faire, mais sans entamer une nouvelle tâche s'il en reste. :-)

    Empiriquement, on peut se laisser une à deux secondes de grâce pour finir ce que l'on est en train de faire quand on reçoit SIGTERM mais guère plus, car lorsque l'on fait un shutdown ou un redémarrage d'un système Unix lors d'un init 0 ou d'un init 6, c'est typiquement ce délai que nous laisse le système : il envoie SIGTERM à tout le monde, attend quelques secondes, puis fais un SIGKILL sur ce qui reste.

  6. #6
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Mars 2013
    Messages
    22
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2013
    Messages : 22
    Par défaut
    Bonjour Obsidian et merci pour cette réponse très enrichissante.

    La solution d'utiliser une structure dédiée aux éléments partagés dans le programme est en effet bien pratique et je m'en vais de ce pas la mettre en oeuvre.
    J'aurai cependant une petite question concernant la sortie ordinaire d'un programme :
    Citation Envoyé par Obsidian
    La bonne réponse, dans ton cas, consiste donc à faire en sorte que ton gestionnaire de signal place un flag quelque part, qui soit interprété ensuite comme une demande de sortie ordinaire par ton programme.
    Dans l'exemple que j'ai formulé dans mon premier message cela reviendrai grosso-modo à remplacer (en considérant pour faire simple une variable globale continuer initialisée à 1) le while(1) ; par while(continuer) ; le handler ayant donc pour simple fonction de mettre la valeur de continuer à zéro, c'est bien ça ? Mais prenons le cas d'un programme travaillant avec des tubes nommés réalisant une ouverture bloquante dans la boucle. L'utilisation de cette méthode propre est donc impossible et du coup pas d'autre solution que d'appeler un atexit() ?

    Autre petite chose au risque de me faire taper sur les doigts : bien que je ne l'ai jamais utilisée et que je ne le souhaite pas, la fumeuse instruction goto ne serait-elle pas utile dans ce dernier cas (sûrement une méthode très sale puisqu'elle casse fortement l'exécution structurelle des instructions mais qui aurai le mérite de fonctionner, et donc de terminer le programme de manière ordinaire, non ?)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Runtime.getRuntime().exec exécute le processus après la fin du programme Java
    Par scalande dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 14/02/2012, 17h56
  2. Erreur bizarre APRES la fin du programme
    Par Papy214 dans le forum C#
    Réponses: 14
    Dernier message: 17/03/2009, 10h37
  3. Réponses: 6
    Dernier message: 22/11/2007, 22h45
  4. [LG] Problème avec la Fonction ReadLn en fin de programme
    Par killermano dans le forum Langage
    Réponses: 6
    Dernier message: 23/07/2005, 15h16
  5. Fin de programme dans une procédure
    Par Sinclair dans le forum Langage
    Réponses: 13
    Dernier message: 29/11/2002, 22h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo