Dans quelles circonstances une section critique Windows peut-elle avoir un nombre de verrous négatif?

Y a-t-il des circonstances dans lesquelles le champ LockCount d’une structure RTL_CRITICAL_SECTION dans Windows peut légitimement être négatif?

Nous suivons un crash TRÈS insaisissable et un symptôme que nous voyons est un CS avec un LockCount négatif. Au moment du crash, le compte est de -6, mais il semble être systématiquement -1, -2, etc.

Avant de partir après cela, en supposant que ce soit une très mauvaise chose, je veux juste vérifier que cette hypothèse est correcte. Je peux trouver peu ou pas d’informations sur le fonctionnement interne de RTL_CRITICAL_SECTION.

Le nombre de verrous négatif est un comportement normal sur certaines versions de Windows. Notez que la signification de ce champ a changé pendant la durée de vie de Windows (voir ci-dessous).

L’interprétation de ces champs privés est une tâche délicate et vous pouvez tirer parti des outils de débogage de section critique dédiés.

Par exemple, voir cet article MSDN donne des détails. En particulier, je pense que cela montre pourquoi une valeur de -6 est parfaitement plausible.

Quelques extraits pertinents:

Les sections critiques peuvent être affichées en mode utilisateur par différentes méthodes. La signification exacte de chaque champ dépend de la version de la version de Microsoft Windows que vous utilisez.

……

Dans Microsoft Windows 2000 et Windows XP, le champ LockCount indique le nombre de fois qu’un thread a appelé la routine EnterCriticalSection pour cette section critique, moins un. Ce champ commence à -1 pour une section critique déverrouillée. Chaque appel de EnterCriticalSection incrémente cette valeur; chaque appel de LeaveCriticalSection le décrémente. Par exemple, si LockCount a la valeur 5, cette section critique est verrouillée, un thread l’a acquis et cinq threads supplémentaires attendent ce verrou.

……

Dans Microsoft Windows Server 2003 Service Pack 1 et versions ultérieures de Windows, le champ LockCount est analysé comme suit:

  • Le bit le plus bas indique le statut du verrou. Si ce bit est 0, la section critique est verrouillée; si c’est 1, la section critique n’est pas verrouillée.
  • Le bit suivant indique si un thread a été réveillé pour ce verrou. Si ce bit est 0, un thread a été réveillé pour ce verrou. si c’est 1, aucun thread n’a été réveillé.
  • Les bits restants sont le complément du nombre de threads en attente du verrou.

Ensuite, il explique comment interpréter un nombre de verrous de -22 . Donc, en résumé, c’est plus difficile que vous ne le pensez!

A partir de là , une explication partielle:

LockCount C’est le champ le plus important dans une section critique. Il est initialisé à une valeur de -1; une valeur de 0 ou plus indique que la section critique est détenue ou possédée. Lorsqu’il n’est pas égal à -1, le champ OwningThread (ce champ n’est pas défini correctement dans WINNT.H-il devrait être un DWORD au lieu d’un HANDLE) contient l’ID de thread qui possède cette section critique. Le delta entre ce champ et la valeur de (RecursionCount -1) indique combien de threads supplémentaires attendent pour acquérir la section critique.