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;
}