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 :

boucle infinie et arrêt du programme


Sujet :

C++

  1. #1
    Membre éprouvé Avatar de avigeilpro
    Homme Profil pro
    Ambulancier
    Inscrit en
    Janvier 2004
    Messages
    880
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Ambulancier
    Secteur : Transports

    Informations forums :
    Inscription : Janvier 2004
    Messages : 880
    Points : 971
    Points
    971
    Par défaut boucle infinie et arrêt du programme
    Bonjour,
    Je ne suis pas sûr de vraiment poster ou il le faut, si ce n'est pas le cas je m'en excuse.
    Voila mon problème, je développe un programme en c++ sur openwrt, ce programme contient une boucle while(1) car il lit en boucle un pipe afin d'effectuer des actions. Le programme fonctionne parfaitement, mais si je tape la commande reboot dans la console, rien ne se passe. Par contre après avoir tué le dit programme via killall, alors le reboot fonctionne. Je suppose donc que ma boucle infinie empêche le système de fermer ce programme. Mon programme est lancé en tant que service (init.d et lien dans rc.d), j'ai essayé d'ajouter "killall mon_prog" dans la fonction stop du script du service, mais sans succès.
    Si quelqu'un a la moindre piste je suis preneur, car pour le moment je reboot en manuel donc je fait le killall avant, mais je voudrais pouvoir programmer un reboot hebdo automatique qui ne fonctionnera pas tant que ce problème ne sera pas réglé.
    Merci d'avance pour toute réponse apportée.
    La connaissance seule ne suffit pas. La vraie compréhension vient de la mise en expérience.
    Règles|FAQ|Tuto

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Salut,

    ne peux-tu pas envoyer une commande au programme ? Commande qui déclencherait l'arrêt du programme.
    Etant un service, il devrait redémarrer tout seul.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Membre éprouvé Avatar de avigeilpro
    Homme Profil pro
    Ambulancier
    Inscrit en
    Janvier 2004
    Messages
    880
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Ambulancier
    Secteur : Transports

    Informations forums :
    Inscription : Janvier 2004
    Messages : 880
    Points : 971
    Points
    971
    Par défaut
    Je le pourrais en effet, mais comment faire en sorte que cette commande soit envoyé lorsque l'on entre la commande "reboot" ? En fait je pense (ce n'est qu'une supposition) que lors de commandes telles que reboot ou bien shutdown, le système envoie une informations a tous les programmes en cours afin de leur demander de se fermer, mon programme ne se fermant pas le système reste en attente. Il doit bien exister des informations quelques part pour fermer un programme correctement lorsque le système s'éteint ?
    La connaissance seule ne suffit pas. La vraie compréhension vient de la mise en expérience.
    Règles|FAQ|Tuto

  4. #4
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Le système d'initialisation envoie un signal à ses processus enregistrés afin qu'ils se terminent proprement. Ce signal est probablement SIGTERM, à vérifier.. Ton programme doit l'intercepter et le traiter.

  5. #5
    Membre éprouvé Avatar de avigeilpro
    Homme Profil pro
    Ambulancier
    Inscrit en
    Janvier 2004
    Messages
    880
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Ambulancier
    Secteur : Transports

    Informations forums :
    Inscription : Janvier 2004
    Messages : 880
    Points : 971
    Points
    971
    Par défaut
    Matt_Houston, j'étais justement en train de travailler dessus, mais je me heurte de nouveau à un problème.
    J'arrive sans problème à intercepter les signaux comme suit :
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <string.h>
     
    static volatile sig_atomic_t srv_shutdown = 0;
     
    static void signal_handler(int sig) {
       // Cleanup and close up stuff here
       srv_shutdown = 1;
    }
     
    int main()
    {
      struct sigaction act;
      memset(&act, 0, sizeof(act));
      act.sa_handler = signal_handler;
      sigemptyset(&act.sa_mask);
      act.sa_flags = 0;
      sigaction(SIGINT,  &act, NULL);
      sigaction(SIGTERM, &act, NULL);
      sigaction(SIGHUP,  &act, NULL);
      sigaction(SIGALRM, &act, NULL);
      sigaction(SIGUSR1, &act, NULL);
     
       while(!srv_shutdown)
       {
          printf("Program processing stuff here.\n");
          sleep(1);
       }
       //close(ppipe);
       return EXIT_SUCCESS;
     
    }
    Mais assez curieusement, lorsque le programme est lancé comme service (script ajouté dans init.d et lien dans rc.d), il ne reçoit aucun signal lorsque la commande reboot est entrée, et continue de la bloquer.
    La connaissance seule ne suffit pas. La vraie compréhension vient de la mise en expérience.
    Règles|FAQ|Tuto

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    De manière générale, une boucle while(1) est, par sa signification même (1 est toujours évalué à true, au même titre que n'importe quelle valeur différente de 0) destinée à ne jamais être arrêtée.

    Dés lors, si tu veux qu'une commande puisse demander à ton programme de redémarrer, il faut utiliser une variable dont la valeur puisse être modifiée en cours de route.

    L'idéal, pour s'assurer que le programme redémarre, serait sans doute de travailler en deux temps :
    une première boucle qui s'assure que l'on ne sortira jamais du programme sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main(){
        while(1){
            try(){
                /* la magie interviendra ici */
            }catch(...){
                // loggons les éventuelles erreurs que nous avons "zappées"
            }
        }
    }
    Et toute la magie consistera à créer une autre boucle dont on pourra sortir à demande, et qui nous assurera que toutes les ressources utilisées seront correctement libérées et recréées dans "leur état de base" (car c'est ca, un "reboot" )

    L'idéal serait sans doute de créer une abstraction proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class MyApp{
    public: 
        /* la vraie boucle principale sera ici */
        void run()
    private:
       bool willExit_{false};
       /* les autres ressources */
    };
    dont la fonction run() rendrait la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void MyApp::run(){
        /* tant que l'application n'a pas recu l'ordre de sortie */
         while(!willExit_){
            /* on fait tout ce qu'on veut, y compris modifier willExit_ en cas de besoin / d'envie ;) */
        }
    }
    Si bien que la fonction main() sera modifiée pour prendre une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main(){
        while(1){
            try(){
                MyApp app;
                app.run()
            }catch(...){
                // loggons les éventuelles erreurs que nous avons "zappées"
            }
        }
    }
    Note que, si tu souhaites pouvoir arrêter l'application (sans la relancer, s'entend), il est tout aussi possible de faire en sorte que run() renvoie une valeur spécifique, et d'utiliser cette valeur comme condition de la sortie de la boucle infinie.

    Cela nous donnerait au final quelque chose comme
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    /* une énumération indiquant le status de l'application */
    enum Status{
        running,
        restart,
        finished
    };
    // Modifions un tout petit peu notre classe pour utiliser cette énumération 
    class MyApp{
    public: 
        /* la vraie boucle principale sera ici */
        Status run()
    private:
       Status status_{running};
       /* les autres ressources */
    };
    // adaptons le code de sa fonction run
    void MyApp::run(){
        /* tant que l'application n'a pas recu l'ordre de sortie */
         while(status_ == running){
            /* on fait tout ce qu'on veut, y faire passer status_ à restart ou à finished en cas de besoin / d'envie ;) */
        }
        /* on renvoie le status (qui sera d'office différent de running) à la fonction main() */
        return status_
    }
     
    // enfin "y a plus qu'à" modifier la fonction main pour prendre le résultat de la fonction run() en compte
    int main(){
        // forcons le status à running
        Status status{running}
        // Tant que l'on n'a pas dit explicitement qu'on voulait l'arrêter définitivement
        while(status!= finished){
            try(){
                MyApp app;
                status = app.run()
            }catch(...){
                // loggons les éventuelles erreurs que nous avons "zappées"
                // NOTE : le status n'est pas modifié si une exception a été lancée
            }
        }
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Remarque à 2 balles pour @koala01, j'éviterais le "}catch(...){" qui ne catch pas tout et qui cache trop de chose par un simple programme "watchdog" "dumper", plus simple, plus fiable et plus flexible.

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par bacelar Voir le message
    Remarque à 2 balles pour @koala01, j'éviterais le "}catch(...){" qui ne catch pas tout et qui cache trop de chose par un simple programme "watchdog" "dumper", plus simple, plus fiable et plus flexible.
    En effet... j'ai hésité à le mettre, d'autant plus que, si exception il y a (par exemple : std::bad_alloc), on peut se dire que c'est parce que les ressources sont mal gérées à la base, et que le simple fait de détruire et de recréer l'instance de la classe ne suffira pas à les libérer proprement...

    pour que le try catch soit efficace (si on oublie, évidemment tous les SIGSEGV et autres SIGXXX), il faudrait au minimum que les ressources manipulées soient toutes correctement détruites lors de la "finalisation" (car, j'ai parlé de faire une classe, mais on pourrait tout aussi bien envisager trois fonctions libres, init(), execute (ou run) et finalize ). Or, le fait qu'une exception remonte si haut semble indiquer que ce ne sera pas le cas
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Membre éprouvé Avatar de avigeilpro
    Homme Profil pro
    Ambulancier
    Inscrit en
    Janvier 2004
    Messages
    880
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Creuse (Limousin)

    Informations professionnelles :
    Activité : Ambulancier
    Secteur : Transports

    Informations forums :
    Inscription : Janvier 2004
    Messages : 880
    Points : 971
    Points
    971
    Par défaut
    bonjour koala01, tout d'abord merci d'essayer de m'aider,
    J'ai tenté de comprendre le code que tu as fournis, mais je ne vois pas à quel moment ton code "capte" le signal envoyé par le système lui demandant de se fermer ?
    Dans mon dernier code, je n'utilise plus une boucle mais
    La connaissance seule ne suffit pas. La vraie compréhension vient de la mise en expérience.
    Règles|FAQ|Tuto

  10. #10
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par avigeilpro Voir le message
    bonjour koala01, tout d'abord merci d'essayer de m'aider,
    J'ai tenté de comprendre le code que tu as fournis, mais je ne vois pas à quel moment ton code "capte" le signal envoyé par le système lui demandant de se fermer ?
    Tout simplement dans la boucle de la fonction run, là où j'ai mis le commentaires /* on fait tout ce qu'on veut, y compris modifier willExit_ en cas de besoin / d'envie ;) */.

    Quant à la manière de le capter, ca, c'est à toi de le définir
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. [NASM] Mettre le programme en pause - boucle infinie
    Par Voitures007 dans le forum x86 16-bits
    Réponses: 6
    Dernier message: 19/12/2010, 17h59
  2. Réponses: 4
    Dernier message: 23/02/2009, 16h42
  3. lancer un programme (boucle infinie)
    Par rodman_10 dans le forum Shell et commandes GNU
    Réponses: 7
    Dernier message: 31/10/2007, 10h33
  4. [VB.NET]Boucle infinie et condition d'arrêt
    Par Benbedo dans le forum Windows Forms
    Réponses: 5
    Dernier message: 31/07/2006, 09h20

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