2010-11-17 30 views
34

J'ai une application qui utilise des compteurs de performance, qui a fonctionné pendant des mois. Maintenant, sur ma machine de développement et une autre machine de développement, elle a commencé à se bloquer lorsque j'appelle PerformanceCounterCategory.Exists. Autant que je sache, ça pend indéfiniment. Peu importe quelle catégorie j'utilise comme entrée, et d'autres applications utilisant l'API présentent le même comportement.Qu'est-ce qui rendrait PerformanceCounterCategory.Exists indéfiniment?

Le débogage (à l'aide de MS Symbol Servers) a montré que c'est un appel à Microsoft.Win32.RegistryKey qui se bloque. Une enquête plus poussée montre qu'il est cette ligne qui pèse:

while (Win32Native.ERROR_MORE_DATA == (r = Win32Native.RegQueryValueEx(hkey, name, null, ref type, blob, ref sizeInput))) { 

Ceci est essentiellement une boucle qui tente d'allouer suffisamment de mémoire pour les données de compteur de performance. Il commence à size = 65000 et fait quelques itérations. Dans le 4ème appel, lorsque size = 520000, Win32Native.RegQueryValueEx se bloque.

De plus, plutôt worringly, je trouve ce commentaire dans la source de référence pour PerformanceCounterLib.GetData:

// Win32 RegQueryValueEx for perf data could deadlock (for a Mutex) up to 2mins in some 
    // scenarios before they detect it and exit gracefully. In the mean time, ERROR_BUSY, 
    // ERROR_NOT_READY etc can be seen by other concurrent calls (which is the reason for the 
    // wait loop and switch case below). We want to wait most certainly more than a 2min window. 
    // The curent wait time of up to 10mins takes care of the known stress deadlock issues. In most 
    // cases we wouldn't wait for more than 2mins anyways but in worst cases how much ever time 
    // we wait may not be sufficient if the Win32 code keeps running into this deadlock again 
    // and again. A condition very rare but possible in theory. We would get back to the user 
    // in this case with InvalidOperationException after the wait time expires. 

Quelqu'un at-il vu ce comportement avant? Que puis-je faire pour résoudre cela?

+2

Très belle recherche, +1. Oui, allez-y et inquiétez-vous, l'ensemble de l'API du compteur de perfos n'a pas été maintenu. Un modèle trop simple qui ne peut plus être verrouillé sur la prochaine version de Windows. Vista a fait une grosse pause. Bonne chance! –

Répondre

24

Ce problème est maintenant corrigé, et comme il n'y a pas eu de réponses ici, j'ajouterai une réponse ici au cas où la question serait trouvée dans de futures recherches.

J'ai finalement corrigé cette erreur en arrêtant le service de spouleur d'impression (en tant que mesure temporaire). Il semble que la lecture des compteurs de performance nécessite effectivement d'énumérer les imprimantes sur le système (confirmé par un vidage WinDbg d'un processus suspendu, où je peux voir dans la trace de la pile que winspool énumère les imprimantes, et est coincé dans un appel réseau). C'est ce qui échouait réellement sur le système (et bien sûr, l'ouverture de la fenêtre "Périphériques et imprimantes" était également bloquée). Cela m'étonne qu'un problème d'imprimante/de réseau puisse réellement faire chuter les compteurs de performance. On pourrait penser qu'il y avait une sorte de fail-safe intégré dans un tel cas.

Ce que je devine, c'est que cela est causé par une mauvaise imprimante/pilote sur le réseau. Je n'ai pas encore réactivé l'impression sur les systèmes affectés, puisque nous recherchons la mauvaise imprimante.

+1

Est-il possible que la lecture des compteurs de performance entraîne le blocage du spouleur d'impression? Lancer une seconde requête pour une ressource qui bloque quelque chose que la première requête doit terminer, ou quelque chose comme ça? Je suppose que cela ne change pas la cause réelle - un mauvais pilote - mais je me demande si le problème ne se manifestera pas à moins que vous ne le provoquiez de la manière que vous avez décrite précédemment. –

+1

Cette réponse nous a aidé à résoudre un problème connexe [new PerformanceCounter()] (http://stackoverflow.com/questions/2868068). Retrait d'une vieille imprimante empêché le blocage et au moins montré un message d'erreur que nous poursuivons. – crokusek

+0

Je rencontre un problème similaire à partir d'un complément Outlook. Quel outil avez-vous utilisé pour déboguer? Actuellement, j'ai Process Monitor, mais j'ai de la difficulté à trouver l'impasse –