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 :

Analyse d'un programme qui se "fige"


Sujet :

C#

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    37
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 37
    Points : 37
    Points
    37
    Par défaut Analyse d'un programme qui se "fige"
    Bonjour à tous!

    Alors là, attention, problème plus d'analyse que de développement "pur"! Experts, idées (même saugrenues)... n'hésitez pas.

    En gros:
    Le problème
    Une application développée en C# winform se "fige" en cours d'usage, mais ceci de manière totalement aléatoire. d'un poste à un autre, le blocage peut survenir après une journée d'utilisation, ou bien au bout de seulement une dizaine de minutes.

    De fait: en tests unitaires, aucun souci. En tests plus intenses, aucun figeage constaté sur les plateaux. Mais... à l'usage réel, avec de nombreuses applis tierces ouvertes... ça se fige. Pire: le figeage est relativement "propre", car on peut basculer sur la fenêtre du client, le processeur n'est pas sollicité outre mesure, et la mémoire n'est pas non plus saturée.

    Les infos concernant le programme
    Threadé, appelant des Dll externes (pour préciser, c'est de la téléphonie), le pogramme appelle une base de données, et donc des DLL tierces. Mes soupçons se portaient sur les dites dll, mais visiblement je n'ai rien trouvé de signifiant à l'usage, d'autant plus que les cas de figeages applicatifs ne se produisent pas spécifiquement en cours de communication (ce qui induit que les dites dll ne sont pas en cours d'utilisation).

    Mes questions
    après avoir collé des logs à la pelle (sans succès), je n'identifie toujours pas le processus/thread qui pourrait provoquer ce souci.
    Alors:
    - Quels outils conseillez vous pour traquer le blocage?
    - Comme le mode débug n'est pas l'idéal pour procéder à des tests d'endurance, vers quoi dois-je me tourner?

    Pas facile, hein?

    Tous les conseils sont les bienvenus!

  2. #2
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    Pour commencer, je créerai dans l'application une forme annexe avec un simple bouton qui affiche un message "hello" et je la lancerai au début de l'application avec un show (non modal).

    Cela permettrait de savoir si l'appli s'est totalement crashée.

    Si la forme annexe continue à tourner (le bouton affiche "hello"), on pourra l'utiliser pour tracer les derniers appels et retours des fonctions appelant les DLL et identifier la fonction responsable du plantage.

    Une fois la fonction identifiée, on pourra spécifiquement encadrer les appels aux DLL.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  3. #3
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 172
    Points : 25 112
    Points
    25 112
    Par défaut
    il y a des profilers pour voir tout ce qui se passe dans l'appli, mais c'est pas forcément simple à utiliser

    sinon avec system.diagnostics.stopwatch tu peux chronométrer l'exécution de morceaux de code, et donc voir lesquels prennent du temps et sont possiblement la source du freeze

    seul le thread principal peut faire freezer l'appli, les thread secondaires ne sont pas utilisé pour le rafraichissement de l'interface

    une connexion à une base de données peut etre longue sur des grosses requetes, ou des requetes qui retournent beaucoup de données
    dans ces cas là, il faut les mettre sur un thread secondaire
    sur sql server, il y a sql server profiler qui permet de voir les requetes qui sont longues à exécuter (pour voir celles qui retournent beaucoup de données c'est faisable aussi mais moins simple)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    37
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 37
    Points : 37
    Points
    37
    Par défaut
    Merci pour ces réponses.

    globalement:
    - Les requêtes BDD sont vraiment très simples (de simples SELECT à des tables minuscules. On ne contrôle que quelques données, rien qui nécessite de la gestion particulière). Je ne cible pas spécifiquement ce bout (quoique... vu le problème) mais la piste de profiler la connexion est une bonne idée.
    - Savoir que c'est le thread principal qui peut figer est intéressant, mais il y a un "truc" qui m'horripile dans la façon dont cela a été développé. Je vais schématiser pour être "clair". En gros, imaginez une barre d'outils où c'est supposé être que des boutons.... où, en fait, c'est un tableau d'images clickables. Pourquoi s'être pris la tête avec ça? Bonne question, je récupère le code tel quel. J'ignore si, par hasard, ce n'est pas la gestion de ce ruban qui pose souci.

    J'ai profilé le programme comme suit:
    - Créé un programme annexe présentant un "serveur" sur un port donné
    - Emis à chaque E/S de thread/boucles vers ce serveur pour le prog principal
    Le tout pour avoir comme du "log", mais sans pour autant provoquer d'écriture par wagons entiers.
    Résultat? Les figeages ne semblent pas se produire durant les boucles, car l'appli est comme "au repos" (pas de passage dans les boucles d'analyse de situation).

    Au-delà: je soupçonne un thread ou une méthode dont une exception est mal gérée, et qui retourne une réponse absurde à un "while" (par exemple). Le while attendant un "true pour sortir, alors que la méthode appelée ne retourne que "false" (suite à une anomalie), la dite boucle ne sort plus, ceci laissant l'appli figée (esthétiquement), ne réagit plus à toute action de clic sur l'interface et ainsi de suite. De plus, je crains que le dit "while" soit dans le thread principal, d'où la difficulté à pister le blocage.

    Là, j'ai lancé le programme pour le week end avec un "écouteur" logiciel qui est capable de détecter les exceptions .NET non traitées; Si en revenant lundi matin au boulot, le dit compteur a grimpé, et que le programme est figé, alors j'aurai, je pense, mis le doigt sur le souci potentiel.

    Cependant, merci pour ces renseignements, et le coup de l'ihm m'intéresse. Je vais tenter cette astuce pour voir si c'est bel et bien le logiciel qui se vautre, ou s'il y a un composant tiers de bancal.

  5. #5
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    je soupçonne un thread ou une méthode dont une exception est mal gérée, et qui retourne une réponse absurde à un "while" (par exemple). Le while attendant un "true pour sortir, alors que la méthode appelée ne retourne que "false" (suite à une anomalie), la dite boucle ne sort plus, ceci laissant l'appli figée (esthétiquement),
    Lorsque ça plante, on peut voir en lançant le gestionnaire de tâche (CTRL-ALT-SUPPR) le pourcentage des ressources CPU utilisée dans la colonne processeur de l'onglet processus. Ce qui donnera une indications sur l'hypothèse de boucle sans fin.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

  6. #6
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 172
    Points : 25 112
    Points
    25 112
    Par défaut
    Citation Envoyé par Graffito Voir le message
    le pourcentage des ressources CPU utilisée dans la colonne processeur de l'onglet processus. Ce qui donnera une indications sur l'hypothèse de boucle sans fin.
    un peu raccourci
    un while true avec un thread.sleep(5) dedans et ca ne dépassera pas forcément 20% tout en étant infini
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  7. #7
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 166
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 166
    Points : 7 418
    Points
    7 418
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par magellan94 Voir le message
    - Les requêtes BDD sont vraiment très simples (de simples SELECT à des tables minuscules. On ne contrôle que quelques données, rien qui nécessite de la gestion particulière). Je ne cible pas spécifiquement ce bout (quoique... vu le problème) mais la piste de profiler la connexion est une bonne idée.
    Vérifie quand même si t'as pas un DEADLOCK dans la base

    Citation Envoyé par magellan94 Voir le message
    Au-delà: je soupçonne un thread ou une méthode dont une exception est mal gérée, et qui retourne une réponse absurde à un "while" (par exemple). Le while attendant un "true pour sortir, alors que la méthode appelée ne retourne que "false" (suite à une anomalie), la dite boucle ne sort plus, ceci laissant l'appli figée (esthétiquement), ne réagit plus à toute action de clic sur l'interface et ainsi de suite. De plus, je crains que le dit "while" soit dans le thread principal, d'où la difficulté à pister le blocage.
    C'est une bonne piste en effet.
    Dans tes while (true), tu devrais ajouter un contrôle du temps d'exécution afin de déclencher un timeout : une DLL externe doit retourner n'importe quoi, ou alors figer. Et ton appli attendant une réponse indéfiniment, elle fige à son tour.

    Du coup, je ferais 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
     
    Datetime t1 = DateTime.Now;
     
    while (true)
    {
         // Ton traitement
         if ((DateTime.Now - t1).TotalSecondes > 30)
         {
              throw new Eception("Youpi tralala j'ai trouvé mon freeze");
         }
    }
    On ne jouit bien que de ce qu’on partage.

  8. #8
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 172
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 172
    Points : 25 112
    Points
    25 112
    Par défaut
    le mieux si tu peux reproduire ca depuis visual studio est qu'au moment du freeze tu clic sur pause, tu verras où en est chaque thread ...

    Citation Envoyé par StringBuilder Voir le message
    Vérifie quand même si t'as pas un DEADLOCK dans la base
    en cas de deadlock une exception est déclenchée sur le thread détruit, donc il l'aurait vu passer en erreur
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  9. #9
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 166
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Février 2010
    Messages : 4 166
    Points : 7 418
    Points
    7 418
    Billets dans le blog
    1
    Par défaut
    Sauf si aucun timeout n'est spécifié sur la connection à la base de données (ou que la personne qui l'a spécifié a confondu "minutes" avec "millisecondes")
    On ne jouit bien que de ce qu’on partage.

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    37
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 37
    Points : 37
    Points
    37
    Par défaut
    Merci pour vos réponses!

    Alors:
    1) Ce n'est pas un deadlock, parce que d'une part je ne fais QUE des SELECT (pour consultation), je ne procède à aucune insertion mise à jour. De plus, les catch sur traitements SQL m'auraient, à minima, envoyé un joli message qui va bien (déjà vérifié avec déco/timeout de base).
    2) La consommation processeur n'est pas signifiante: j'ai un processus à 0% (GRRRRR!), avec une consommation mémoire totalement stable. Pire encore: comme on est sur du thread avec des "sleep" (comme mentionné par une des réponses), même une boucle infinie ne donnera pas une surconsommation processeur signifiante.
    3) J'ai une piste étrange grâce à Dependancy walker: STATUS_STACK_BUFFER_OVERRUN. J'ai vérifié pas mal de choses suggérées sur le net, mais la plupart sont, en tout cas apparemment, hors sujet. Mes déclarations de variables semblent conformes (pas de tableaux à dimensions en dur, appels "cleans" de dll...). donc, soit il y a un truc dans une DLL externe, soit j'ai loupé un bout de code pernicieux. Quoi qu'il en soit, je continue à tracker cette piste pour le moment.
    4) Je n'arrive malheureusement pas à reproduire le blocage à travers le mode debug. C'est la montée en charge, voire des évènements à l'usage qui semblent déclencher la "boucle infinie" que je soupçonne.

    Concrètement:
    - débugger n'est pas réellement significatif.
    - Les anomalies de figeage se produisent de manière aléatoire, avec des délais plus ou moins longs.
    - bizarrement, certaines machines sont plus sensibles (répétition plus forte, sur une donnée donnée)
    - En contrôlant les logs applicatifs, zéro anomalie.
    - On a contrôlé, par acquis de conscience, tous les cas de sortie des switch, while, foreach, histoire de s'assurer qu'aucun n'ait de cas non prévu. A l'instant où j'écris ce post, je n'ai rien trouvé qu justifierait une boucle infinie... si ce n'est l'appel à des méthodes non catchées (s'il en reste, on vérifie).

    Autre chose, qui est une idée potentiellement "débile"... mais vu où j'en suis! Si une exception est levée et non surveillée par un try/catch, existe-t-il un moyen de l'écouter depuis une application tierce? Process explorer est, par exemple, capable d'écouter les anomalies .NET et de remonter un compteur, mais sans détail sur l'anomalie levée. Y a-t-il une façon d'obtenir ces erreurs potentielles? Qui sait, peut-être a-t-on une exception non gérée que je pourrais alors analyser!

    Merci à tous, ce que vous proposez me fait avancer en tout cas.

  11. #11
    Membre confirmé Avatar de NicoL__
    Homme Profil pro
    Architecte
    Inscrit en
    Janvier 2011
    Messages
    399
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte

    Informations forums :
    Inscription : Janvier 2011
    Messages : 399
    Points : 577
    Points
    577
    Par défaut
    Une exception non gérée fait planter le programme, il s'arrête et normalement dans les journaux de la machine on doit trouver quelque chose surement dans le journal "Application".
    Le pire étant de mal gérer les erreur... ce qui peut entrainer un programme dans un état impossible et le freezer par exemple.
    Sinon il y a peut-être ne production un autre programme qui accède à la base de données (ou une ressource partagée) qui entraine un lock. Un select peut être locker dans certain cas, (on peut ajouter with (nolock) mais la garantie de la qualité des données n'est plus certaine...

Discussions similaires

  1. Réponses: 6
    Dernier message: 05/03/2013, 18h33
  2. Lister les processus - programme qui se fige
    Par filaos974 dans le forum Allegro
    Réponses: 0
    Dernier message: 25/10/2007, 19h15
  3. Programme qui analyse un fichier log
    Par abdou.sahraoui dans le forum Entrée/Sortie
    Réponses: 9
    Dernier message: 20/08/2004, 14h27

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