2009-11-16 9 views
1

Je débogue ce projet de base de données. Il encapsule l'accès à SQLite pour une application de niveau supérieur. Il est conçu pour s'exécuter de manière asynchrone, c'est-à-dire qu'il possède des méthodes telles que ExecuteRequestAsync() et IsRequestReady(). Quand ExecuteRequestAsync est appelé, il engendre un boost :: thread pour faire le travail et retourner la fonction immédiatement. Lorsque l'application de niveau supérieur décide qu'elle ne veut plus le résultat d'une requête en cours, elle peut appeler DumpRequest() pour l'annuler. Comme il est difficile d'annuler gracieusement une requête de base de données, l'implémentation de DumpRequest maintient simplement un "thread de surveillance de nettoyage" qui attend les "requêtes terminées" et les supprime. Tous les boost :: threads sont gérés par boost :: shared_ptr, comme:boost :: thread causant un petit événement gérer une fuite?

boost::shared_ptr<boost::thread> my_thread = new boost::thread(boost::bind(&DBCon::RunRequest, &this_dbcon)); 

Et quand il n'y a pas besoin de plus (à annuler):

vector<boost::shared_ptr<boost::thread> > threads_tobe_removed; 
// some iteration 
threads_tobe_removed[i].get()->join(); 
threads_tobe_removed.erase(threads_tobe_removed.begin()+i); 

J'ai créé ce projet de test unitaire pour tester la mécanisme d'exécution et de dumping des demandes. Il exécute les requêtes et annule aléatoirement les demandes en cours, et répète plusieurs milliers de passages. Le mécanisme s'est avéré être correct. Tout a fonctionné comme prévu. Cependant, en observant le projet de test unitaire à travers l'Explorateur de processus de sysinternal, il est découvert qu'il existe un problème de fuite de poignée. Chaque passe de 500-ish, le nombre de handles augmente de 1, et ne revient jamais. C'est le handle de type "Event" qui augmente. Les poignées de fichier et de thread n'augmentent pas (bien sûr, le nombre de poignées augmente au fur et à mesure que les threads sont générés, mais il y a un appel Sleep (10000) toutes les cent passes pour qu'elles soient nettoyées afin d'observer le nombre de handles).

Je n'ai pas géré les handles d'événement moi-même. Ils sont créés par boost :: thread lors de la création du thread. Je garantis seulement de fermer les threads avec élégance, je n'ai aucune idée de ce que les événements sont utilisés.

Je me demande si quelqu'un a connu des problèmes similaires? Quelle pourrait être la cause de cette fuite? Ce numéro dans Process Explorer est-il assez fiable pour l'appeler fuite de handle? Y a-t-il un moyen de tracer et de réparer? J'utilise boost boost statiquement 1.40 sur Windows Vista, avec Visual C++.

+0

La génération de 100 requêtes et leur vidage immédiat prend normalement environ 3 secondes sur Intel CoreDuo E6600. Et le nombre maximal de handles ouverts est d'environ 300 (y compris l'événement, le thread, les fichiers et autres). Lorsque le test passe en état de sommeil, le nombre de poignées ouvertes descend graduellement à 65 environ. Chaque passage de 500, fait passer le nombre "fin" de 65 à 66, puis 67. C'est en fait une fois toutes les 50 000 exécutions. C'est très bizarre et frustrant. –

+0

"le nombre de poignées ouvertes diminue progressivement" car le thread du moniteur de nettoyage les collecte. –

Répondre

1

L'accès à threads_tobe_removed est-il sécurisé? Si ce n'est pas le cas, il peut y avoir une condition de concurrence, lorsqu'un thread ajoute un thread au vecteur via un appel à DumpRequest, tandis que le thread du moniteur de nettoyage supprime un thread du vecteur. Ainsi, boost::thread - les objets peuvent être détruits sans joindre le fil en premier, ce qui laisserait le fil tourner sans objet associé, ce qui pourrait expliquer la fuite.

+0

Bien sûr, il est verrouillé en utilisant un mutex. La synchronisation n'est pas un problème ici. Le verrouillage est effectué si nécessaire. Sinon, cela ne provoquerait-il pas une fuite de handle de thread à la place de handle d'événement? Ce qui est bizarre, c'est que la fuite ne se produit qu'avec 0,2% de la demande. –

+2

Je pense qu'une fuite de 0,2% est beaucoup plus probable que tout autre nombre. Les contributeurs Boost sont des codeurs talentueux. Le ne manquerait pas une simple fuite à 100%.Il est beaucoup plus probable que la fuite provienne d'une condition de course subtile qui arrive rarement. Cependant, par défaut je suppose que boost fait la bonne chose, si vous pensez vraiment que vous avez trouvé quelque chose dépouiller à la plus petite quantité de code qui va reproduire le problème et frapper les listes de diffusion boost. –

Questions connexes