[NTOSKRNL]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Thu, 20 Dec 2012 14:58:02 +0000 (14:58 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Thu, 20 Dec 2012 14:58:02 +0000 (14:58 +0000)
- Use 2 seperate SEH blocks in PsSuspendThread(). This way we don't leak the rundown protection, and don't keep a terminating thread suspended, when KeSuspendThread() throws an exception. Also only catch STATUS_SUSPEND_COUNT_EXCEEDED exceptions in the SEH filter.

svn path=/trunk/; revision=57958

reactos/ntoskrnl/ps/state.c

index 62664f9..8baeea0 100644 (file)
@@ -45,73 +45,78 @@ PsResumeThread(IN PETHREAD Thread,
 
 NTSTATUS
 NTAPI
-PsSuspendThread(IN PETHREAD Thread,
-                OUT PULONG PreviousCount OPTIONAL)
+PsSuspendThread(
+    IN PETHREAD Thread,
+    OUT PULONG PreviousCount OPTIONAL)
 {
     NTSTATUS Status;
     ULONG OldCount = 0;
     PAGED_CODE();
 
-    /* Guard with SEH because KeSuspendThread can raise an exception */
-    _SEH2_TRY
+    /* Assume success */
+    Status = STATUS_SUCCESS;
+
+    /* Check if we're suspending ourselves */
+    if (Thread == PsGetCurrentThread())
     {
-        /* Check if we're suspending ourselves */
-        if (Thread == PsGetCurrentThread())
+        /* Guard with SEH because KeSuspendThread can raise an exception */
+        _SEH2_TRY
         {
             /* Do the suspend */
             OldCount = KeSuspendThread(&Thread->Tcb);
-
-            /* We are done */
-            Status = STATUS_SUCCESS;
         }
-        else
+        _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_SUSPEND_COUNT_EXCEEDED)
         {
-            /* Acquire rundown */
-            if (ExAcquireRundownProtection(&Thread->RundownProtect))
+            /* Get the exception code */
+            Status = _SEH2_GetExceptionCode();
+        }
+        _SEH2_END;
+    }
+    else
+    {
+        /* Acquire rundown protection */
+        if (ExAcquireRundownProtection(&Thread->RundownProtect))
+        {
+            /* Make sure the thread isn't terminating */
+            if (Thread->Terminated)
             {
-                /* Make sure the thread isn't terminating */
-                if (Thread->Terminated)
+                /* Fail */
+                Status = STATUS_THREAD_IS_TERMINATING;
+            }
+            else
+            {
+                /* Guard with SEH because KeSuspendThread can raise an exception */
+                _SEH2_TRY
                 {
-                    /* Fail */
-                    Status = STATUS_THREAD_IS_TERMINATING;
+                    /* Do the suspend */
+                    OldCount = KeSuspendThread(&Thread->Tcb);
                 }
-                else
+                _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_SUSPEND_COUNT_EXCEEDED)
                 {
-                    /* Otherwise, do the suspend */
-                    OldCount = KeSuspendThread(&Thread->Tcb);
-
-                    /* Check if it terminated during the suspend */
-                    if (Thread->Terminated)
-                    {
-                        /* Wake it back up and fail */
-                        KeForceResumeThread(&Thread->Tcb);
-                        Status = STATUS_THREAD_IS_TERMINATING;
-                        OldCount = 0;
-                    }
+                    /* Get the exception code */
+                    Status = _SEH2_GetExceptionCode();
                 }
+                _SEH2_END;
 
-                /* Release rundown protection */
-                ExReleaseRundownProtection(&Thread->RundownProtect);
-
-                /* We are done */
-                Status = STATUS_SUCCESS;
-            }
-            else
-            {
-                /* Thread is terminating */
-                Status = STATUS_THREAD_IS_TERMINATING;
+                /* Check if it was terminated during the suspend */
+                if (Thread->Terminated)
+                {
+                    /* Wake it back up and fail */
+                    KeForceResumeThread(&Thread->Tcb);
+                    Status = STATUS_THREAD_IS_TERMINATING;
+                    OldCount = 0;
+                }
             }
-        }
-    }
-    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-    {
-        /* Get the exception code */
-        Status = _SEH2_GetExceptionCode();
 
-        /* Don't fail if we merely couldn't write the handle back */
-        if (Status != STATUS_SUSPEND_COUNT_EXCEEDED) Status = STATUS_SUCCESS;
+            /* Release rundown protection */
+            ExReleaseRundownProtection(&Thread->RundownProtect);
+        }
+        else
+        {
+            /* Thread is terminating */
+            Status = STATUS_THREAD_IS_TERMINATING;
+        }
     }
-    _SEH2_END;
 
     /* Write back the previous count */
     if (PreviousCount) *PreviousCount = OldCount;