Author: tkreuzer
Date: Thu Dec 20 14:58:02 2012
New Revision: 57958
URL:
http://svn.reactos.org/svn/reactos?rev=57958&view=rev
Log:
[NTOSKRNL]
- 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.
Modified:
trunk/reactos/ntoskrnl/ps/state.c
Modified: trunk/reactos/ntoskrnl/ps/state.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/state.c?rev=57…
==============================================================================
--- trunk/reactos/ntoskrnl/ps/state.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ps/state.c [iso-8859-1] Thu Dec 20 14:58:02 2012
@@ -45,73 +45,78 @@
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
- {
- /* Check if we're suspending ourselves */
- if (Thread == PsGetCurrentThread())
+ /* Assume success */
+ Status = STATUS_SUCCESS;
+
+ /* 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
- {
- /* Acquire rundown */
- if (ExAcquireRundownProtection(&Thread->RundownProtect))
+ }
+ _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_SUSPEND_COUNT_EXCEEDED)
+ {
+ /* 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
- {
- /* 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;
- }
- }
-
- /* Release rundown protection */
- ExReleaseRundownProtection(&Thread->RundownProtect);
-
- /* We are done */
- Status = STATUS_SUCCESS;
+ /* Fail */
+ Status = STATUS_THREAD_IS_TERMINATING;
}
else
{
- /* Thread is terminating */
- Status = STATUS_THREAD_IS_TERMINATING;
+ /* Guard with SEH because KeSuspendThread can raise an exception */
+ _SEH2_TRY
+ {
+ /* Do the suspend */
+ OldCount = KeSuspendThread(&Thread->Tcb);
+ }
+ _SEH2_EXCEPT(_SEH2_GetExceptionCode() == STATUS_SUSPEND_COUNT_EXCEEDED)
+ {
+ /* Get the exception code */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* 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;
- }
- _SEH2_END;
+
+ /* Release rundown protection */
+ ExReleaseRundownProtection(&Thread->RundownProtect);
+ }
+ else
+ {
+ /* Thread is terminating */
+ Status = STATUS_THREAD_IS_TERMINATING;
+ }
+ }
/* Write back the previous count */
if (PreviousCount) *PreviousCount = OldCount;