Author: tkreuzer Date: Mon Jan 21 20:58:23 2013 New Revision: 58200
URL: http://svn.reactos.org/svn/reactos?rev=58200&view=rev Log: [NTOSKRNL] Some keyed event fixes: disable APCs before acquiring the pushlock, close handle on exception, check if a wait was aborted and remove the wait list entry from the list in that case.
Modified: trunk/reactos/ntoskrnl/ex/keyedevt.c
Modified: trunk/reactos/ntoskrnl/ex/keyedevt.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/keyedevt.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/ex/keyedevt.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ex/keyedevt.c [iso-8859-1] Mon Jan 21 20:58:23 2013 @@ -142,6 +142,7 @@ HashIndex %= NUM_KEY_HASH_BUCKETS;
/* Lock the lists */ + KeEnterCriticalRegion(); ExAcquirePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock);
/* Get the lists for search and wait, depending on whether @@ -161,6 +162,10 @@ ListEntry = WaitListHead1->Flink; while (ListEntry != WaitListHead1) { + /* Get the waiting thread. Note that this thread cannot be terminated + as long as we hold the list lock, since it either needs to wait to + be signaled by this thread or, when the wait is aborted due to thread + termination, then it first needs to acquire the list lock. */ Thread = CONTAINING_RECORD(ListEntry, ETHREAD, KeyedWaitChain);
/* Check if this thread is a correct waiter */ @@ -170,11 +175,16 @@ /* Remove the thread from the list */ RemoveEntryList(&Thread->KeyedWaitChain);
+ /* Initialize the list entry to show that it was removed */ + InitializeListHead(&Thread->KeyedWaitChain); + /* Wake the thread */ KeReleaseSemaphore(&Thread->KeyedWaitSemaphore, 0, 1, FALSE); - - /* Unlock the lists */ + Thread = NULL; + + /* Unlock the list. After this it is not safe to access Thread */ ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock); + KeLeaveCriticalRegion();
return STATUS_SUCCESS; } @@ -192,8 +202,9 @@ /* Insert the current thread into the secondary wait list */ InsertTailList(WaitListHead2, &CurrentThread->KeyedWaitChain);
- /* Unlock the lists */ + /* Unlock the list */ ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock); + KeLeaveCriticalRegion();
/* Wait for the keyed wait semaphore */ Status = KeWaitForSingleObject(&CurrentThread->KeyedWaitSemaphore, @@ -202,7 +213,26 @@ Alertable, Timeout);
- return STATUS_SUCCESS; + /* Check if the wait was aborted or timed out */ + if (Status != STATUS_SUCCESS) + { + /* Lock the lists to make sure no one else messes with the entry */ + KeEnterCriticalRegion(); + ExAcquirePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock); + + /* Check if the wait list entry is still in the list */ + if (CurrentThread->KeyedWaitChain.Flink != &CurrentThread->KeyedWaitChain) + { + /* Remove the thread from the list */ + RemoveEntryList(&CurrentThread->KeyedWaitChain); + } + + /* Unlock the list */ + ExReleasePushLockExclusive(&KeyedEvent->HashTable[HashIndex].Lock); + KeLeaveCriticalRegion(); + } + + return Status; }
_IRQL_requires_max_(APC_LEVEL) @@ -274,7 +304,7 @@ /* Check for success */ if (!NT_SUCCESS(Status)) return Status;
- /* Initalize the keyed event */ + /* Initialize the keyed event */ ExpInitializeKeyedEvent(KeyedEvent);
/* Insert it */ @@ -353,6 +383,9 @@ { /* Get the exception code */ Status = _SEH2_GetExceptionCode(); + + /* Cleanup */ + ObCloseHandle(KeyedEventHandle, PreviousMode); } _SEH2_END; }