- Fix behavior of KeRundownQueue (save the next link before freeing it and use proper locking and enumeration code).

- This fixes behavior of I/O completion ports (thanks to Stefan and Alex for testing, reporting and fixing).

svn path=/trunk/; revision=37212
This commit is contained in:
Aleksey Bragin 2008-11-05 17:03:04 +00:00
parent 04b0bb8994
commit b21beacd60

View file

@ -436,8 +436,7 @@ PLIST_ENTRY
NTAPI NTAPI
KeRundownQueue(IN PKQUEUE Queue) KeRundownQueue(IN PKQUEUE Queue)
{ {
PLIST_ENTRY ListHead, NextEntry; PLIST_ENTRY FirstEntry, NextEntry;
PLIST_ENTRY FirstEntry = NULL;
PKTHREAD Thread; PKTHREAD Thread;
KIRQL OldIrql; KIRQL OldIrql;
ASSERT_QUEUE(Queue); ASSERT_QUEUE(Queue);
@ -446,34 +445,41 @@ KeRundownQueue(IN PKQUEUE Queue)
/* Get the Dispatcher Lock */ /* Get the Dispatcher Lock */
OldIrql = KiAcquireDispatcherLock(); OldIrql = KiAcquireDispatcherLock();
/* Make sure the list is not empty */ /* Check if the list is empty */
if (!IsListEmpty(&Queue->EntryListHead)) FirstEntry = Queue->EntryListHead.Flink;
if (FirstEntry == &Queue->EntryListHead)
{ {
/* Remove it */ /* We won't return anything */
FirstEntry = RemoveHeadList(&Queue->EntryListHead); FirstEntry = NULL;
} }
else
/* Unlink threads and clear their Thread->Queue */
ListHead = &Queue->ThreadListHead;
NextEntry = ListHead->Flink;
while (ListHead != NextEntry)
{ {
/* Get the Entry's Thread */ /* Remove this entry */
RemoveEntryList(&Queue->EntryListHead);
}
/* Loop the list */
while (!IsListEmpty(&Queue->ThreadListHead))
{
/* Get the next entry */
NextEntry = Queue->ThreadListHead.Flink;
/* Get the associated thread */
Thread = CONTAINING_RECORD(NextEntry, KTHREAD, QueueListEntry); Thread = CONTAINING_RECORD(NextEntry, KTHREAD, QueueListEntry);
/* Kill its Queue */ /* Clear its queue */
Thread->Queue = NULL; Thread->Queue = NULL;
/* Remove this entry */ /* Remove this entry */
RemoveEntryList(NextEntry); RemoveEntryList(NextEntry);
/* Get the next entry */
NextEntry = NextEntry->Flink;
} }
/* Release the lock and return */ /* Release the dispatcher lock */
KiReleaseDispatcherLock(OldIrql); KiReleaseDispatcherLockFromDpcLevel();
/* Exit the dispatcher and return the first entry (if any) */
KiExitDispatcher(OldIrql);
return FirstEntry; return FirstEntry;
} }