Skip to content

Commit fe7a58d

Browse files
committed
[RTL] Update CountOfOwnedCriticalSections in the TEB
Useful for debugging. Motivation: With SMP on x64 I found a number of instances where critical sections would be left abandoned, causing lockups. From what I can tell it was exceptions inside rpcrt4, which leave the process in a blocked state. Might or might not be related to x64 / SMP. For real value, you still need to put checks at certain places manually, but this is not super straight forward, because there can be false positives, e.g. when a process is terminated due to an exception, where the abandoned lock is acceptable, and we have this during testing. It's difficult to 100% distinguish this from silent and very bad lock leaks. Problematic code: __try { SomeFunction(); // throws an exception with a CS held, e.g. heap code } __except(1) { DPRINT1("Oops. let's just pretend it's all ok!\n"); }
1 parent 848ad61 commit fe7a58d

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

sdk/lib/rtl/critical.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ RtlEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
521521
*/
522522
CriticalSection->OwningThread = Thread;
523523
CriticalSection->RecursionCount = 1;
524+
NtCurrentTeb()->CountOfOwnedCriticalSections++;
524525
return STATUS_SUCCESS;
525526
}
526527

@@ -800,6 +801,7 @@ RtlLeaveCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
800801
* See comment above.
801802
*/
802803
CriticalSection->OwningThread = 0;
804+
NtCurrentTeb()->CountOfOwnedCriticalSections--;
803805

804806
/* Was someone wanting us? This needs to be done atomically. */
805807
if (-1 != InterlockedDecrement(&CriticalSection->LockCount))
@@ -837,8 +839,9 @@ RtlTryEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection)
837839
if (InterlockedCompareExchange(&CriticalSection->LockCount, 0, -1) == -1)
838840
{
839841
/* It's ours */
840-
CriticalSection->OwningThread = NtCurrentTeb()->ClientId.UniqueThread;
842+
CriticalSection->OwningThread = NtCurrentTeb()->ClientId.UniqueThread;
841843
CriticalSection->RecursionCount = 1;
844+
NtCurrentTeb()->CountOfOwnedCriticalSections++;
842845
return TRUE;
843846
}
844847
else if (CriticalSection->OwningThread == NtCurrentTeb()->ClientId.UniqueThread)

0 commit comments

Comments
 (0)