https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fe7a58d92eeb571dffec4ad93efec945b372869a
commit fe7a58d92eeb571dffec4ad93efec945b372869a Author: Timo Kreuzer <timo.kreu...@reactos.org> AuthorDate: Thu Dec 12 14:48:29 2024 +0200 Commit: Timo Kreuzer <timo.kreu...@reactos.org> CommitDate: Sat Jan 18 21:15:17 2025 +0200 [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"); } --- sdk/lib/rtl/critical.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sdk/lib/rtl/critical.c b/sdk/lib/rtl/critical.c index c70ff191bbc..4678230e57b 100644 --- a/sdk/lib/rtl/critical.c +++ b/sdk/lib/rtl/critical.c @@ -521,6 +521,7 @@ RtlEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) */ CriticalSection->OwningThread = Thread; CriticalSection->RecursionCount = 1; + NtCurrentTeb()->CountOfOwnedCriticalSections++; return STATUS_SUCCESS; } @@ -800,6 +801,7 @@ RtlLeaveCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) * See comment above. */ CriticalSection->OwningThread = 0; + NtCurrentTeb()->CountOfOwnedCriticalSections--; /* Was someone wanting us? This needs to be done atomically. */ if (-1 != InterlockedDecrement(&CriticalSection->LockCount)) @@ -837,8 +839,9 @@ RtlTryEnterCriticalSection(PRTL_CRITICAL_SECTION CriticalSection) if (InterlockedCompareExchange(&CriticalSection->LockCount, 0, -1) == -1) { /* It's ours */ - CriticalSection->OwningThread = NtCurrentTeb()->ClientId.UniqueThread; + CriticalSection->OwningThread = NtCurrentTeb()->ClientId.UniqueThread; CriticalSection->RecursionCount = 1; + NtCurrentTeb()->CountOfOwnedCriticalSections++; return TRUE; } else if (CriticalSection->OwningThread == NtCurrentTeb()->ClientId.UniqueThread)