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

C Discussion :

Relance de processus fils morts : la bonne pratique ?


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Profil pro
    Lycéen
    Inscrit en
    Août 2007
    Messages
    3
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Août 2007
    Messages : 3
    Par défaut Relance de processus fils morts : la bonne pratique ?
    Bonjour à tous,

    Je suis en train de créer un programme sous Linux qui crée notamment des processus fils pour des traitements spécifiques.
    J'ai donc un processus parent et ses fils. Je voudrais, quand un fils meurt, qu'il soit automatiquement relancé par le père. Pour cela, je comptais utiliser les signaux UNIX : à la réception de SIGCHLD, le père, via une fonction de signal handler, fait un wait et relance le processus fils via un fork.

    Un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    void funcHandler(int signal)
    {
    	if (signal == SIGCHLD)
    	{
    		pid_t fils = wait(NULL);
     
    		if (fils == pidPremierFils)
    		{
    			if ((pidPremierFils = fork()) == 0)
    			{
    				PremierFils();
    			}
    		}
             }
    }
    Je me pose du coup ces questions :

    1. A-t-on le "droit" de faire un fork dans un signal handler ? Pour le processus fils, ça change quelque chose ?
    2. Si on a un premier signal (mort du premier fils), on va dans le signal handler. Par malchance, pendant ce temps, un deuxième signal arrive (mort du deuxième fils) : n'est-ce pas dangereux ? Notamment si le programme est en train de faire le fork ?
    3. Du coup, pendant qu'on est dans le signal handler, vaut-il mieux bloquer les autres signaux ? Dans ce cas, les signaux seront-ils "supprimés" ou bien retardés à la fin de traitement du signal handler et donc bien capturés ?

    D'une manière générale, est-ce la bonne manière de faire ? Ou alors quelle est la manière de gérer la relance de processus fils sous Linux ?

    Merci d'avance.

  2. #2
    Membre émérite
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Par défaut
    Voilà un problème bien classique de programmation système.

    Le man 7 signal dit que la fonction fork peut être appellée de manière sûre dans un gestionnaire de signaux.

    Par contre, ce qu'il peut se passer c'est que :
    - fork modifie errno, donc selon l'endroit où le signal a interrompu ton programme principal, si tu ne restaure pas errno avant de finir le handler de signal, tu ne sais pas ce qu'il peut se passer.
    - Si deux signaux arrivent en même temps, ils s'écrasent et tu n'en reçois qu'un seul. Les signaux normaux ne sont pas comptés. (Ou plus exactement : si un signal arrive alors qu'un autre signal est déjà en attente de traitement, alors le handler ne sera appellé qu'une seule fois.)

    Et comme de toutes façons il va falloir que tu maintienne une liste des tâches en cours (qui sera globale), tu risques d'avoir des soucis si dans ton handler de signal tu manipules une variable globale alors que le le programme principal était lui aussi en train de la manipuler.

    C'est donc pour ça que la méthode propre que je recommanderais c'est de :
    - limiter le handler de signal à flag = 1 plus ou moins ;
    - ne pas mettre d'option SA_RESTART à l'appel de sigaction ;
    - masquer le SIGCHLD quand tu modifie tes structures globales ;
    - démasquer le SIGCHLD uniquement quand tu fais des appels système bloquant ;
    - gérer toi-même le redémarrage de l'appel système après avoir fait autant de fork que tu as fait de wait pour nettoyer les zombies (et après avoir remis flag = 0 quand tu t'es assuré que tu n'as plus de fils mort).

  3. #3
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 875
    Par défaut
    Une question que je me pose : comment savoir quel fils a envoye le signal SIGCHLD ? Je crois qu'on peut connaitre le pid du programme envoyant ce signal grace a sigaction, mais il faudrait alors l'avoir stocke en global quelque part pour y avoir acces, non ?

  4. #4
    Membre émérite
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Par défaut
    As-tu réellement besoin de le savoir quel fils est mort au moment où tu reçois le SIGCHLD ?

    Oui, sigaction peut te donner le pid du fils mort si tu as mis le flag SA_SIGINFO. Cependant, tu devrais garder ton handler aussi court que possible pour les raisons sus-citées.

    Et de toutes façons, tu vas appeller wait ou waitpid pour nettoyer le zombie, et à ce moment là tu auras le pid du fils mort.

  5. #5
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 875
    Par défaut
    Donc en gros il faut faire un wait sur tous les fils pour verifier lequel est mort ? Y a pas mieux comme methode ?

  6. #6
    Membre émérite
    Avatar de Celelibi
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    1 087
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 1 087
    Par défaut
    Non, tu fais un wait une fois qu'il est mort.
    wait attend la terminaison d'un fils, n'importe lequel.
    De même si tu donnes le pid -1 à waitpid : il attendra la terminaison de n'importe quel processus fils et te renverra une erreur si tous les fils sont déjà morts. Et si tu donnes l'option WNOHANG à waitpid il te renverra 0.

    D'ailleurs, est-ce que ton programme principal fait autre chose pendant que les fils se terminent ?
    Parce que si ton programme ne fait rien d'autre que relancer les processus qui se terminent, alors tu n'as même pas besoin de jouer avec les signaux et ton programme se résume à peu de choses près à :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while (1) {
        pid = wait(NULL);
        rerun_process(pid);
    }
    Faut juste pas oublier de vérifier les erreurs (si wait te renvoi -1) et vérifier que le processus est bien mort (avec les macros WIFEXITED et WIFSIGNALED).

    Et de toutes façons, t'es obligé de soit faire un wait soit donner l'option SA_NOCLDWAIT. Sans ça, tu vas avoir des zombies qui traînent.
    Cela dit, il faut noter qu'avec l'option SA_NOCLDWAIT tu n'as aucune garanti que le handler de signal soit appellé. Il le sera sous Linux, il le sera pas sous d'autres Unix.

    Conclusion : Pour un programme portable, t'es obligé de faire des wait ou waitpid.

Discussions similaires

  1. Bonnes pratiques de protections individuelles
    Par Community Management dans le forum Sécurité
    Réponses: 23
    Dernier message: 11/06/2024, 12h23
  2. [Bonne pratique]Stratégie d'allocation
    Par jowo dans le forum C
    Réponses: 1
    Dernier message: 05/10/2005, 15h47
  3. [FOREIGN K] Valeur de champ = nom de table. Bonne pratique ?
    Par Seb des Monts dans le forum Langage SQL
    Réponses: 9
    Dernier message: 17/05/2005, 11h56
  4. Partage d'une variable entre les processus fils
    Par Mehdi Feki dans le forum Linux
    Réponses: 7
    Dernier message: 09/01/2005, 14h34

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