mirror of
https://github.com/reactos/reactos.git
synced 2024-09-29 05:54:05 +00:00
[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. svn path=/trunk/; revision=57958
This commit is contained in:
parent
589a2f3a3c
commit
7d2114ddb1
|
@ -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
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release rundown protection */
|
||||
ExReleaseRundownProtection(&Thread->RundownProtect);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Thread is terminating */
|
||||
Status = STATUS_THREAD_IS_TERMINATING;
|
||||
}
|
||||
}
|
||||
_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;
|
||||
|
||||
/* Write back the previous count */
|
||||
if (PreviousCount) *PreviousCount = OldCount;
|
||||
|
|
Loading…
Reference in a new issue