https://git.reactos.org/?p=reactos.git;a=commitdiff;h=fe7a58d92eeb571dffec4…
commit fe7a58d92eeb571dffec4ad93efec945b372869a
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Thu Dec 12 14:48:29 2024 +0200
Commit: Timo Kreuzer <timo.kreuzer(a)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)