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 :

Le Sleep ne bloque pas l'arrêt du service


Sujet :

C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 44
    Par défaut Le Sleep ne bloque pas l'arrêt du service
    Bonjour,

    j'ai développé un petit service qui, sans rentrer dans les détails, fait quelques actions puis se met en veille pendant 10 minutes grâce à un Sleep(600000);
    Je pensais que si j'essayais d'arrêter le service pendant qu'il est en veille, le Sleep empêcherait celui ci de s'arrêter. Mais ce n'est pas le cas, le service s'arrête aussitôt.
    Je trouve ça bizarre, c'est comme si le processus était killé, le reste des instructions n'étant pas exécutées.
    Ce qui m'amène à me demander si le service se termine proprement...

    Est ce que quelqu'un a un avis la dessus?

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 44
    Par défaut
    Je précise quand même que tout se passe dans la fonction ServiceMain

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
    {
         //quelques instructions
         ...
         ...
         Sleep(600000);
         ...
         //encore des instructions
         ...
    }

  3. #3
    Membre chevronné Avatar de seeme
    Profil pro
    Inscrit en
    Octobre 2005
    Messages
    430
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Octobre 2005
    Messages : 430
    Par défaut
    En toute logique, ce qu'il se passe, c'est que la demande de kill est transmise (probablement avec un signal) malgré le sleep.

    J'avoue que je ne connais pas assez l'API win32, mais je pense que c'ets une piste à suivre.

  4. #4
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Bonjour.

    La fonction Sleep n'est pas bloquante. Elle ne fait que rendre la main au processeur qui "endort" l'application. Celui-ci viendra la réveiller une fois le délai écoulé.

    Pour être certain que ton programme se quitte proprement il faut gérer l'évènement SERVICE_CONTROL_STOP et libérer les ressources.

  5. #5
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Exact, Sleep ne bloque pas les signaux reçus.
    D'ailleurs, aucune fonction ne le fait.

    Il faut gérer manuellement les signaux pour avoir un contrôle fin dessus.
    Par exemple, sous UNIX, pour ignorer le signal d'interruption (Ctrl + C) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #include <csignal>
     
    signal(SIGINT, SIG_IGN);
    On peut également définir un gestionnaire de signaux afin de faire exécuter du code particulier (paix à son âme…) lorsqu'un signal donné est intercepté.

    Il y a certainement un moyen similaire de le faire sous Windows, mais je ne connais pas non plus très bien l'API win32.
    Donc je ne peux pas t'aider plus.

  6. #6
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Citation Envoyé par moldavi Voir le message
    La fonction Sleep n'est pas bloquante.
    Bah si, justement : elle bloque/suspend le thread courant…

  7. #7
    la_tupac
    Invité(e)
    Par défaut
    La fonction Sleep n'est pas bloquante. Elle ne fait que rendre la main au processeur qui "endort" l'application. Celui-ci viendra la réveiller une fois le délai écoulé.
    J'ai peut-être mal compris, mais c'est bien ça qu'il voulait. Mais apparament le service doit générer un exception... Sleep est-il correctement géré pas l'api Win32 (pareil je ne suis pas calé). Mon conseil: essaye de débuguer ou vérifie que les instruction après Sleep sont bien effectuées ...

    ps: renseigne-toi, il doit y avoir une autre methode de sleep pour win32 (c'est vieux Sleep

  8. #8
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Bonjour à tous.

    Lorsque je dis que la fonction Sleep n'est pas bloquante, c'est qu'elle ne mobilise pas le processeur. Bien sûr qu'elle bloque le programme au niveau du code, mais pas au sens de l'application gérée par le processeur. Un service n'a pas de boucle de message comme une interface graphique, la gestion des deux sous windows est différente.

    Faîtes une boucle while(true); et vous comprendrez la différence avec un Sleep.

    Citation Envoyé par Steph_ng8 Voir le message
    Bah si, justement : elle bloque/suspend le thread courant…
    Confère ci-dessus. La question n'est pas de savoir si le thread est bloqué/suspendu, mais pourquoi il peut-être arrêter lorsqu'il est dans un Sleep. Et là c'est surtout une question de fonctionnement des services windows qui n'a rien à voir avec une application graphique. Un service que l'on essaie d'arrêter avec la console adéquate, parfois ne s'arrête pas.

  9. #9
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Arf, on ne devait pas parler de la même chose.
    J'ai toujours entendu ou lu le terme « bloquant » (du moins l'expression « opérations bloquante ») dans le sens « bloque le programme et ne rend la main que lorsqu'elle est terminée ».

    En passant, sous Linux, sleep aussi peut être interrompue par un signal.
    D'ailleurs, la valeur qu'elle retourne est le nombre de secondes restant par rapport à la durée passée en paramètre.

  10. #10
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 44
    Par défaut
    merci pour vos réponses.

    Citation Envoyé par Steph_ng8 Voir le message
    En passant, sous Linux, sleep aussi peut être interrompue par un signal.
    D'ailleurs, la valeur qu'elle retourne est le nombre de secondes restant par rapport à la durée passée en paramètre.
    Je n'ai pas trouvé de fonction mieux que Sleep sous windows. Je ne pense pas qu'on puisse l'interrompre.

    je gère l'événement SERVICE_CONTROL_STOP, voici mon gestionnaire de messages :

    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
    void WINAPI ServCtrlHandler(DWORD SCCode)
    {
        switch(SCCode)
        {
        case SERVICE_CONTROL_CONTINUE:
            ServiceStatus.dwCurrentState = SERVICE_RUNNING;
            if((SetServiceStatus (hServiceStatus,&ServiceStatus))==0)
                erreur();
            return;
     
        case SERVICE_CONTROL_PAUSE:
            ServiceStatus.dwCurrentState = SERVICE_PAUSED;
            if((SetServiceStatus (hServiceStatus,&ServiceStatus))==0)
                erreur();
            return;
     
        case SERVICE_CONTROL_STOP:
            ServiceStatus.dwWin32ExitCode = 0;
            ServiceStatus.dwCurrentState = SERVICE_STOPPED;
            ServiceStatus.dwCheckPoint = 0;
            ServiceStatus.dwWaitHint = 0;
            if((SetServiceStatus (hServiceStatus,&ServiceStatus))==0)
                erreur();
            ServiceStarted=FALSE;
            return;
        }
    }
    Le problème doit venir de ServiceStatus.dwCheckPoint et ServiceStatus.dwWaitHint qui sont à 0, ce qui signifie si j'ai bien compris que le service s'arrête sans délai.
    Du coup, si je dois gérer l'arrêt, il faut que je puisse mettre fin au Sleep quand je veux...

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 44
    Par défaut
    je peux peut-être utiliser la fonction WaitForSingleObject avec un handle bidon à la place du Sleep
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    DWORD WINAPI WaitForSingleObject(
      __in  HANDLE hHandle,
      __in  DWORD dwMilliseconds
    );
    Cette fonction s'arrête quand le temps est écoulé ou que le handle change d'état, mais je trouve que c'est du gros bidouillage.

    je peux aussi utiliser un timer que l'on peut arrêter quand on veut avec un KillTimer.

  12. #12
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Je pense que l'explication est ailleurs.

    Dans un service, il y a au moins 2 threads.
    • Le thread ServiceMain() qui peut être considéré comme le thread principal de l'application service.
    • Le thread de contrôle qui est géré par le Service Control Manager. C'est ce thread qui reçoit les commande start, stop, suspend, ... et qui doit les traiter.

    Dans ton cas, le thread de controle reçoit bien les commandes et il y réagit bien mais j'ai l'impression qu'il ne signale pas au thread principal qu'il faut s'arrêter. Il est possible que ton thread principal continue à s'exécuter (jusqu'à la fin du sleep() bien que le thread de contrôle ait signalé qu'il était arrêté.

    Il faudrait que tu regarde avec le gestionnaire de tâches ou même avec process explorer ce qui se passe au niveau des thread pour ton service lorsque la commande stop est envoyée.
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 44
    Par défaut
    Je viens d'essayer avec le gestionnaire de tâches et process explorer.
    Quand j'arrête le service dans la console, le processus disparaît aussitôt.

  14. #14
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Bonjour.

    Vous voulez absolument que votre code après le Sleep soit exécuté lorsque le service est arrêté afin de quitter proprement. Ai-je bien compris ?

    En partant de cette hypothèse, je dirai qu'il s'agit d'un problème de conception. Le code qui libère les ressources doit être accessible depuis l'extérieur du thread. Ou par exemple, les ressources sont gérées par une classe qui les libère à la destruction de la classe.

    Il faut aussi savoir que certaines ressources sont libérées par le système automatiquement à la fin du processus. Donc pas d'inquiétude pour ces ressources.

    Expliquez plus en détail les ressources à libérer qui vous inquiètent.

  15. #15
    la_tupac
    Invité(e)
    Par défaut
    Le thread de contrôle qui est géré par le Service Control Manager. C'est ce thread qui reçoit les commande start, stop, suspend, ... et qui doit les traiter.
    Pouquoi ne pas utiliser ce qui existe ? si le thread ControlManager peut être suspendu, pourquoi ne pas intégrer le code dans ce dernier et envoyer une commande suspend...

  16. #16
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par la_tupac Voir le message
    Pouquoi ne pas utiliser ce qui existe ? si le thread ControlManager peut être suspendu, pourquoi ne pas intégrer le code dans ce dernier et envoyer une commande suspend...
    Le suspend est prévu pour que le système puisse suspendre le service, pas pour que le service puisse se suspendre lui même (auquel cas il aura bien du mal à redémarrer tout seul).

    Le problème est évidemment que le thread de contrôle n'est pas le thread principal du service. Pour contourner la difficulté, il suffit d'ajouter une synchronisation dans le thread de contrôle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    case SERVICE_CONTROL_STOP:
       WaitForSingleObject(mon_event_de_synchro, INFINITE);
    Dans le thread de service :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    mon_event_de_synchro = CreateEvent(...);
    ...
    Sleep(60000);
    ...
    SetEvent(mon_event_de_synchro);
    A noter que Windows pourrait décider que vous êtes particulièrement méchant, et tuer violemment le service s'il décide qu'il a attendu trop longtemps. Je ne peux pas le confirmer ceci-dit (ça fait longtemps que je n'ai pas mis les mimines dans les noirs secrets de Windows).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    44
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 44
    Par défaut
    merci Emmanuel, j'ai trouvé cette solution hier sur ce tutorial qui est très bien expliqué : http://www.alrj.org/docs/systeme/win32thread.pdf

    Par contre j'ai fait l'inverse de ce que tu dis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    case SERVICE_CONTROL_STOP:
       SetEvent(mon_event_de_synchro);
    Dans le thread de service :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    mon_event_de_synchro = CreateEvent(...);
    ...
    ...
    WaitForSingleObject(mon_event_de_synchro, 6000000);
    le WaitForSingleObject bloque le thread pendant 10 minute ou jusqu'à ce qu'on fasse le SetEvent.
    Du coup, ça débloque tout quand on arrête le service.
    Et en plus, j'ai modifié un peu mon SERVICE_CONTROL_STOP,
    j'ai mis ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; à la place de ServiceStatus.dwCurrentState = SERVICE_STOPPED;
    Ce qui permet de me laisser le temps de quitter mes thread proprement avant que le service s'arrête.

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

Discussions similaires

  1. [CSemaphore] pourquoi ca me bloque pas ?
    Par ZaaN dans le forum MFC
    Réponses: 6
    Dernier message: 16/03/2007, 09h37
  2. Réponses: 6
    Dernier message: 13/04/2006, 15h54
  3. Réponses: 8
    Dernier message: 25/11/2005, 18h38
  4. time.sleep() ne fonctionne pas comme souhaité
    Par Olivier_ dans le forum Général Python
    Réponses: 3
    Dernier message: 19/11/2005, 01h46
  5. [Thread] PB Thread.sleep(1000) marche pas
    Par kliel dans le forum Concurrence et multi-thread
    Réponses: 6
    Dernier message: 03/12/2004, 13h47

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