J'ai une application Windows très importante et complexe (Million + LOC) écrite en C ++. Nous recevons une poignée de rapports tous les jours que l'application s'est enfermée et doit être fermée avec force. p>
Bien que nous ayons des rapports détaillés sur les accidents en place, j'aimerais développer cela pour inclure ces scénarios suspendus - même avec une forte journalisation en place, nous n'avons pas été en mesure de suivre les causes profondes pour certaines d'entre elles. Nous pouvons clairement voir où l'activité s'est arrêtée - mais pas pourquoi em> elle s'est arrêtée, même dans l'évaluation de la production de tous les filets. p>
Le problème est de la détection lorsqu'une suspension se produit. Jusqu'à présent, le meilleur que je puisse arriver est un fil de garde de surveillance (comme nous avons la preuve que les threads de fond se poursuivent pour exécuter des problèmes de sortie) qui sort périodiquement la fenêtre principale avec un message personnalisé et confirme qu'il est manipulé dans un mode opportun. Cela ne ferait que capturer un fil de l'interface graphique de l'interface graphique, mais cela semble être là où la majorité d'entre eux se produisent. Si une réponse n'a pas été reçue dans un délai configurable, nous capturions une vidage de mémoire et de pile et donnez à l'utilisateur la possibilité de continuer à attendre ou à redémarrer l'application. p>
Est-ce que quelqu'un connaît une meilleure façon de le faire qu'un tel interrogation périodique de la fenêtre principale de cette manière? Cela semble douloureusement maladroit, mais je n'ai pas vu de remplacement qui fonctionnera sur nos plateformes - Windows XP et Windows 2003 Server. Je vois que Vista a beaucoup de meilleurs outils pour cela, mais malheureusement cela ne nous aidera pas. p>
Il suffit de dire que nous avons fait de nombreux diagnostics à ce sujet et que nous avons rencontré uniquement un succès limité. Notez que la fixation de WINDBG en temps réel n'est pas une option, car nous ne recevons pas les rapports avant les heures ou les jours après l'incident. Nous serions en mesure de récupérer une mémoire de mémoire et des fichiers journaux, mais rien de plus. p>
Toute suggestion au-delà de ce que je planifie ci-dessus serait appréciée. P>
4 Réponses :
une suggestion: p>
En supposant que le problème soit due à la verrouillage, vous pourriez jeter vos états Mutex & Sempaphore à partir d'un fil de surveillance. Avec un peu de travail (traçage de votre graphique de vos appels), vous pouvez déterminer comment vous êtes arrivé sur une impasse, quels chemins d'appel bloquent mutuellement, etc. P>
Merci, c'est une bonne suggestion après avoir détecté le fait que nous sommes enfermés - mais je cherche d'abord à trouver un moyen fiable de le faire.
Une option consiste à exécuter votre programme sous votre propre "débogueur" tout le temps. Certains programmes, tels que GeRight, font ceci pour la protection de la copie, mais vous pouvez également le faire pour détecter les suspensions. Essentiellement, vous incluez dans votre programme certains code pour joindre à un processus via l'API de débogage, puis utilisez cette API pour vérifier périodiquement la suspension. Lorsque le programme commence pour la première fois, il vérifie s'il y a un débogueur attaché à celui-ci et, sinon, il exécute une autre copie de lui-même et la joint à elle - la première instance ne fait que rien d'autre que le débogueur et le deuxième instance est le "réel "Un. P>
Comment vous vérifiez réellement que les hangs est une autre question complète, mais avoir accès à l'API de débogage, il devrait y avoir un moyen de vérifier raisonnablement efficacement si la pile a changé ou non (c'est-à-dire sans charger tous les symboles). Néanmoins, vous n'avez peut-être pas seulement besoin de le faire toutes les quelques minutes environ, alors même si ce n'est pas efficace, cela pourrait être correct. P>
C'est une solution quelque peu extrême, mais devrait être efficace. Il serait également assez facile de transformer ce comportement sur et éteint - un commutateur de ligne de commande fera ou un #define si vous préférez. Je suis sûr qu'il y a du code qui fait des choses comme ça déjà, alors vous n'avez probablement pas à le faire à partir de zéro. P>
Merci, je vais jeter un oeil à ça. Je suis préoccupé par les frais généraux impliqués. L'application est déjà énorme et en raison de la nature partagée de l'environnement des services Terminal Services, nous avons atteint un point où l'ajout de la mémoire de mémoire significative ou de la CPU pourrait être problématique.
Bien qu'une analyse de CrashDump semble fournir une solution pour identifier le problème, dans mon expérience, cela porte rarement beaucoup de fruits car il manque suffisamment de détails sans ambiguïté de ce qui s'est passé juste avant le crash. Même avec l'outil que vous proposez, cela fournirait peu plus que des preuves circonstancielles de ce qui s'est passé. Je parie que la cause est des données partagées non protégées, donc une trace de verrouillage ne le montrerait pas. P>
Le moyen le plus productif de trouver cela - dans mon expérience - distiller la logique de l'application à son essence et identifier l'emplacement des conflits. Combien de fils y a-t-il? Combien sont des interfaces graphiques? À combien de points les threads interagissent-ils? Oui, c'est une bonne vérification de vieux bureau. Les principales interactions suspectes peuvent être identifiées dans un jour ou deux, puis convaincre un petit groupe de sceptiques que l'interaction est correcte. P>
True, et nous avons certainement essayé cela (et continuons à essayer), mais jusqu'à présent, nous n'avons pas été en mesure de reproduire cela sous ses formes d'origine ni dans une forme "coupée". Même après avoir identifié les interactions suspectes potentielles, nous ne pouvons toujours pas forcer le scénario à se produire. Je ne m'attends pas à ce que la décharge soit la balle magique, mais plutôt une autre arme puissante dans l'Arsenal-- ayant une trace de pile peut donner de nombreuses informations, même sans aucune des autres données, la décharge ne contiendra.
Je ne veux pas faire de code distillé runnable. Je veux dire distiller le code sur son noyau fonctionnel et ses interactions, comme sur un morceau de papier ou de tableau blanc: Task1: Initialiser; boucle; wait_for_signal; perform_listbox_update; jusqu'à ce que (terminé); code>
Nous nous sommes également approchés de cet angle. Beaucoup de problème est qu'il y a plusieurs chemins différents que cela semble conduire à cela - nous ne sommes donc pas confrontés à une cause première.
La réponse est simple: sendmessagetimeout strong>! p>
Utilisation de cette API, vous pouvez envoyer un message à une fenêtre et attendre un délai d'attente avant de continuer; Si l'application répond avant le délai d'attente, le cas échéant, sinon, il est suspendu. p>
Merci, je ne savais pas à propos de celui-ci - ça va bien travailler avec ce que je planifie déjà.
On dirait que MQ_TIMEDSEND () code> pourrait l'équivalent Linux à ceci. Je parle juste de ce que je lis, pas d'expérience. Linux.die.net/man/3/mq_send
Quand il se bloque, tous les threads se verrouillent? L'application continue-t-elle de générer des fichiers journaux?
Voulez-vous que l'application elle-même de la détecter a accroché ou a un processus distinct pour surveiller l'application une option?
L'application fait - dans la plupart des scénarios - continuez à générer de la journalisation dans d'autres threads que la fenêtre principale. Dans un très faible pourcentage de cas, il apparaît que toute la journalisation s'arrête sur les threads. Nous cherchons à avoir la demande d'auto-surveillance.