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)

Reply via email to