Author: ion Date: Sun Jul 23 21:45:30 2006 New Revision: 23249
URL: http://svn.reactos.org/svn/reactos?rev=23249&view=rev Log: - Acquire Process lock when touching the thread list entry and incrementing the process' active threads. - Set the Thread Create Time on creation, I had forgotten this! - Handle failures for thread-safety/race conditions. If the process was deleted or the thread terminated behind our back, then go through a manual un-initalization code path. - Just like previous process patch, add code to now create an access state with SeCreateAccessStateEx. - Handle failure of ObInsertObject.
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h trunk/reactos/ntoskrnl/include/internal/ob.h trunk/reactos/ntoskrnl/ke/kthread.c trunk/reactos/ntoskrnl/ps/thread.c
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/k... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ke.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ke.h Sun Jul 23 21:45:30 2006 @@ -291,6 +291,12 @@ IN PVOID KernelStack );
+VOID +NTAPI +KeUninitThread( + IN PKTHREAD Thread +); + NTSTATUS NTAPI KeInitThread(
Modified: trunk/reactos/ntoskrnl/include/internal/ob.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/o... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ob.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ob.h Sun Jul 23 21:45:30 2006 @@ -195,6 +195,13 @@
LONG FASTCALL +ObDereferenceObjectEx( + IN PVOID Object, + IN ULONG Count +); + +LONG +FASTCALL ObReferenceObjectEx( IN PVOID Object, IN ULONG Count
Modified: trunk/reactos/ntoskrnl/ke/kthread.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/kthread.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ke/kthread.c (original) +++ trunk/reactos/ntoskrnl/ke/kthread.c Sun Jul 23 21:45:30 2006 @@ -726,6 +726,15 @@ IN PVOID ThreadState) { UNIMPLEMENTED; +} + +VOID +NTAPI +KeUninitThread(IN PKTHREAD Thread) +{ + /* Delete the stack */ + MmDeleteKernelStack(Thread->StackBase, FALSE); + Thread->InitialStack = NULL; }
NTSTATUS
Modified: trunk/reactos/ntoskrnl/ps/thread.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/thread.c?rev=23... ============================================================================== --- trunk/reactos/ntoskrnl/ps/thread.c (original) +++ trunk/reactos/ntoskrnl/ps/thread.c Sun Jul 23 21:45:30 2006 @@ -146,6 +146,9 @@ KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status; HANDLE_TABLE_ENTRY CidEntry; + ACCESS_STATE LocalAccessState; + PACCESS_STATE AccessState = &LocalAccessState; + AUX_DATA AuxData; PAGED_CODE();
/* If we were called from PsCreateSystemThread, then we're kernel mode */ @@ -299,7 +302,21 @@ return Status; }
- /* FIXME: Acquire exclusive pushlock */ + /* Lock the process */ + KeEnterCriticalRegion(); + ExAcquirePushLockExclusive(&Process->ProcessLock); + + /* Make sure the proces didn't just die on us */ + if (Process->ProcessDelete) goto Quickie; + + /* Check if the thread was ours, terminated and it was user mode */ + if ((Thread->Terminated) && + (ThreadContext) && + (Thread->ThreadsProcess == Process)) + { + /* Cleanup, we don't want to start it up and context switch */ + goto Quickie; + }
/* * Insert the Thread into the Process's Thread List @@ -312,7 +329,9 @@ /* Start the thread */ KeStartThread(&Thread->Tcb);
- /* FIXME: Wake pushlock */ + /* Release the process lock */ + ExReleasePushLockExclusive(&Process->ProcessLock); + KeLeaveCriticalRegion();
/* Release rundown */ ExReleaseRundownProtection(&Process->RundownProtect); @@ -333,13 +352,43 @@ /* Check if we were already terminated */ if (Thread->Terminated) KeForceResumeThread(&Thread->Tcb);
+ /* Create an access state */ + Status = SeCreateAccessStateEx(NULL, + ThreadContext ? + PsGetCurrentProcess() : Process, + &LocalAccessState, + &AuxData, + DesiredAccess, + &PsThreadType->TypeInfo.GenericMapping); + if (!NT_SUCCESS(Status)) + { + /* Access state failed, thread is dead */ + InterlockedOr(&Thread->CrossThreadFlags, CT_DEAD_THREAD_BIT); + + /* If we were suspended, wake it up */ + if (CreateSuspended) KeResumeThread(&Thread->Tcb); + + /* Dispatch thread */ + OldIrql = KeAcquireDispatcherDatabaseLock (); + KiReadyThread(&Thread->Tcb); + KeReleaseDispatcherDatabaseLock(OldIrql); + + /* Dereference completely to kill it */ + ObDereferenceObjectEx(Thread, 2); + } + /* Insert the Thread into the Object Manager */ Status = ObInsertObject(Thread, - NULL, + AccessState, DesiredAccess, 0, NULL, &hThread); + + /* Delete the access state if we had one */ + if (AccessState) SeDeleteAccessState(AccessState); + + /* Check for success */ if (NT_SUCCESS(Status)) { /* Wrap in SEH to protect against bad user-mode pointers */ @@ -356,6 +405,18 @@ } _SEH_END; } + else + { + /* Thread insertion failed, thread is dead */ + InterlockedOr(&Thread->CrossThreadFlags, CT_DEAD_THREAD_BIT); + + /* If we were suspended, wake it up */ + if (CreateSuspended) KeResumeThread(&Thread->Tcb); + } + + /* Get the create time */ + KeQuerySystemTime(&Thread->CreateTime); + ASSERT(!(Thread->CreateTime.HighPart & 0xF0000000));
/* Set the thread access mask */ Thread->GrantedAccess = THREAD_ALL_ACCESS; @@ -370,6 +431,24 @@
/* Return */ return Status; + + /* Most annoying failure case ever, where we undo almost all manually */ +Quickie: + /* When we get here, the process is locked, unlock it */ + ExReleasePushLockExclusive(&Process->ProcessLock); + + /* Uninitailize it */ + KeUninitThread(&Thread->Tcb); + + /* If we had a TEB, delete it */ + if (TebBase) MmDeleteTeb(Process, TebBase); + + /* Release rundown protection, which we also hold */ + ExReleaseRundownProtection(&Process->RundownProtect); + + /* Dereference the thread and return failure */ + ObDereferenceObject(Thread); + return STATUS_PROCESS_IS_TERMINATING; }
/* PUBLIC FUNCTIONS **********************************************************/