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 :

Stopper une fonction en cours d'execution


Sujet :

C

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 59
    Points : 33
    Points
    33
    Par défaut Stopper une fonction en cours d'execution
    Bonjour.
    Voila mon problème :
    j'ai un programme non threadé (et je ne souhaite pas qu'il le soit).
    J'aimerais que certaines fonctions dispose d'un timeout, c'est a dire que la fonction "toto()" ne doit pas avoir un temps d'execution de plus de 15 secondes. SI il elle dépasse, elle se coupe (ou se fait couper) et on passe apres la fonction. Avec des thread ca serait facilement faisable, mais je ne peux en utiliser.
    J'ai recherché sur internet, et j'ai vu un exemple ou quelqun utilise la fonction "alarm()" puis appelle une fonction. au bout du timeout, un SIGALARM est émis, et il "catch" ce sigalarm. Le souci est que dans l'exemple, dans le catch, le programme est coupé. Hors moi je ne souhaite pas qu'il soit coupé, mais qu'il passe apres la fonction.

    Avez vous des pistes ?
    merci d'avec

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 76
    Points : 46
    Points
    46
    Par défaut re:
    si tu veu qu'une fonctione se coupe en un temps definit je pensse que tu devrais trouver une methode pour calculer le temps de cette fonction lors de son execution .

    je sais pas si sa existe ce principe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    fonction(){
         definit un temps <----- fonction X;
     
         /* corp de la fonction */
     
         /* un signal est envoyer par la fonction X des que le temps est atteind */
     
         si on receptione le signal
                    on quit la fonction
    }
    si tu as une boucle je pensse comme sa:

    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
     
    fonction(){
          definit une variable tempsTotal, X, Y
          sauvegarde d'un temps X
     
          while(??){
     
               /* corp de boucle */
     
               sauvegarde d'un temps Y
               tempsTotal = Y - X
     
               Si(tempsTotal >= 15 sec)
                     on quit la fonction
          }
    }
    voila mes idées mais desoler si cette fonction X existe je ne l'a connais pas lol

  3. #3
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Ben y a même des exemples complets (pour UNIX) sur le net si t'as bien cherché. http://cedric.cnam.fr/~bouzefra/livr...tre2/timeout.c. C'est plus facile à décortiquer qu'un hello world. Dans un programme C ANSI on regarde plutôt l'heure après chaque instruction élémentaire (chaque point-virgule si tu veux ...), si on a dépassé un certain temps on quitte immédiatement la fonction. Et bien sûr c'est très moche.

  4. #4
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Après chaque instruction élémentaire ?
    C'est rare, ça. Généralement, les fonctions longues ont une boucle (voire plusieurs imbriquées), donc c'est seulement à chaque itération qu'on vérifie le temps passé...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 59
    Points : 33
    Points
    33
    Par défaut
    Citation Envoyé par Melem Voir le message
    Ben y a même des exemples complets (pour UNIX) sur le net si t'as bien cherché. http://cedric.cnam.fr/~bouzefra/livr...tre2/timeout.c. C'est plus facile à décortiquer qu'un hello world. Dans un programme C ANSI on regarde plutôt l'heure après chaque instruction élémentaire (chaque point-virgule si tu veux ...), si on a dépassé un certain temps on quitte immédiatement la fonction. Et bien sûr c'est très moche.
    J'ai effectivement testé cet exemple.
    Mais comme je le dis dans mon premier message, cet exemple coupe le programme si le signal est catché. Hors moi je ne veux pas que ca se coupe, mais que ca termine la fonction. Dans cet exemple si on vire le exit(), la fonction continue.

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Il faut que ton gestionnaire de signal modifie une variable globale volatile, et que ta fonction, vérifie régulièrement que si la variable globale a été modifiée ou non, auquel cas elle quitte.

    Ou bien, tu peux peut-être le faire avec setjmp()/longjmp(), je ne me souviens plus si les signaux l'interdisent ou non...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Membre averti Avatar de Jack_serious
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    350
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 350
    Points : 396
    Points
    396
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Il faut que ton gestionnaire de signal modifie une variable globale volatile, et que ta fonction, vérifie régulièrement que si la variable globale a été modifiée ou non, auquel cas elle quitte.

    Ou bien, tu peux peut-être le faire avec setjmp()/longjmp(), je ne me souviens plus si les signaux l'interdisent ou non...
    Les deux peuvent cohabiter sans probleme.

    C'est juste qu'il faut commencer a faire tres attention car l'excecution du programme ressemble vite a un chat sur une table de ping-pong.
    Et ca devient tres amusant a debugger.
    Don't worry, be serious.
    La vie est courte. Prenez votre temps.

    Jack.

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Je sais, j'ai déjà goûté à ASP.NET et ses timeouts...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Expert éminent
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Points : 8 389
    Points
    8 389
    Par défaut
    Citation Envoyé par eponyme Voir le message
    J'ai effectivement testé cet exemple.
    Mais comme je le dis dans mon premier message, cet exemple coupe le programme si le signal est catché. Hors moi je ne veux pas que ca se coupe, mais que ca termine la fonction. Dans cet exemple si on vire le exit(), la fonction continue.
    T'as qu'à remplacer exit par un longjmp vers ta fonction.

    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
    #include <unistd.h>
    #include <signal.h>
    #include <setjmp.h>
     
    struct sigaction action;
    jmp_buf jmp_buffer;
     
    void fonction(void);
    void Hand_Sigalarm(void);
     
    int main ()
    {
        action.sa_handler = Hand_Sigalarm;
        sigaction(SIGALRM, &action, NULL);
     
        fonction();
     
        return 0;
    }
     
    void fonction()
    {
        int status;
     
        alarm(15); /* timeout = 15 s */
        status = setjmp(jmp_buffer);
     
        if (status == 0)
        {
           /* Tu mets tout ton code ici */
            ...
        }
     
         alarm(0);
    }
     
    void Hang_Sigalarm()
    {
        longjmp(jmp_buf, <tout sauf 0>);
    }

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 59
    Points : 33
    Points
    33
    Par défaut
    Merci beaucoup melem !
    j'ai un peu adapté ton code à mes besoins :
    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
     
    #include <unistd.h>
    #include <signal.h>
    #include <setjmp.h>
     
    struct sigaction action;
    jmp_buf jmp_buffer;
     
    void fonction(void);
    void Hand_Sigalarm(void);
    int catched = 0;
     
    int main ()
    {
        action.sa_handler = Hand_Sigalarm;
        sigaction(SIGALRM, &action, NULL);
        alarm(5);
        setjmp(jmp_buffer);
        if ( catched == 0 )
            fonction();
        printf("apres\n");
        return 0;
    }
     
    void fonction()
    {
            while(1)
            {
                    printf("boucle\n");
                    sleep(1);
            }
    }
     
    void Hand_Sigalarm()
    {
        printf("CATCHED !\n");
        catched = 1 ;
        longjmp(jmp_buffer,1);
    }
    Donc ce que je fais, c'est qu'avant d'appeller la fonction "timoutée", je sauvegarde le contexte, puis je verifie si mon flag "catched" n'a pas changé (ce qui voudrais dire que la fonction à déja été appellée), puis j'appelle ma fonction qui boucle dans le vide. Au bout de 5 secondes le signal est déclanché, je change mon flag, et je repars avec longjmp, et le flag ayant changé, je n'appelle pas la fonction et repars apres.
    Ca fonctionne bien, je ne sais pas si il y a "plus propre". En tout cas merci ca fonctionne super bien.

    Dernier petit détail, pour ne faut il surtout pas mettre 0 en second argument de longjmp ?

  11. #11
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    Parce qu'en "théorie", ça ferait une boucle infinie (setjmp() retournerait encore 0, donc on réessaierai, etc.).

    En pratique, il me semble que longjmp() est protégé contre ça, et que si tu lui passes 0 setjmp() retourne 1 quand même. Mais j'ignore si c'est inscrit dans la norme ou si c'est un comportement de mon implémentation de l'époque...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Médinoc, c'est demande par la norme (au moins C99, j'ai pas C90 sous la main).

    L'utilisation de {long,set}jmp dans un gestionnaire de signal a des problemes. Sous Unix voir sig{long,set}jmp pour une version plus controlable.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  13. #13
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    76
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 76
    Points : 46
    Points
    46
    Par défaut re:
    Dans lexemple d'eponyme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    while(1)
            {
                    printf("boucle\n");
                    sleep(1);
            }
    pourquoi une boucle infinie je comprend pas trop. On aurait pu mettre une condition de sorti par rapport a un temps final directement non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     
    On declare tempsFinal, tempsX, tempsY
     
    On initialise tempsX
     
    while(tempsFinal < 15sec)
            {
                    On affect un temps a tempsY
                    tempsFinal = Y - X;
                    Affiche boucle
                    met en pause le processus
     
            }

  14. #14
    Membre averti Avatar de Jack_serious
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    350
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2005
    Messages : 350
    Points : 396
    Points
    396
    Par défaut
    Citation Envoyé par john93 Voir le message
    Dans lexemple d'eponyme:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    while(1)
            {
                    printf("boucle\n");
                    sleep(1);
            }
    pourquoi une boucle infinie je comprend pas trop. On aurait pu mettre une condition de sorti par rapport a un temps final directement non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     
    On declare tempsFinal, tempsX, tempsY
     
    On initialise tempsX
     
    while(tempsFinal < 15sec)
            {
                    On affect un temps a tempsY
                    tempsFinal = Y - X;
                    Affiche boucle
                    met en pause le processus
     
            }
    La boucle infinie c'est juste un exemple pour illustrer une fonction qui fait un traitement tres lourd et qui aurait par consequent besoin d'un timout.
    Don't worry, be serious.
    La vie est courte. Prenez votre temps.

    Jack.

  15. #15
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 59
    Points : 33
    Points
    33
    Par défaut
    Effectivement

    Et de plsu je cherchat un truc "générique". Je n'ai pas une fonction avec un timout, mais en fait une cinquantaine (toutes avec le meme prototype). Donc j'aurai une fonction "executer_fonction", qui prendra un pointeur de fonction en argument, qui armera le timeout, et qui le gerera, sans que j'ai a modifier les fonctions pour qu'elles gerent elles meme le timeout.

    Merci a tous pour votre aide

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

Discussions similaires

  1. [XL-2007] Stopper une macro en cours d'execution avec un boutton
    Par pastis.vi dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 10/07/2013, 15h20
  2. relancer une fonction en cours d'execution
    Par flyingfr53 dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 07/07/2011, 09h13
  3. passer des data a une fonction en cours d'execution
    Par benooo dans le forum Interfaces Graphiques
    Réponses: 2
    Dernier message: 18/06/2011, 11h17
  4. Réponses: 1
    Dernier message: 19/01/2010, 14h48
  5. Réponses: 4
    Dernier message: 07/11/2006, 11h28

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