[ros-dev] KQUEUE race condition

Alex Ionescu ionucu at videotron.ca
Sat Nov 20 20:04:04 CET 2004


Hi,

Why not hold the lock all the way through?

Best regards,
Alex Ionescu

Filip Navara wrote:

> Hi,
>
> I think I found a race condition in KQUEUE code, but I'm not sure my 
> solution is optimal. If no items are queued, KeRemoveQueue calls 
> KeWaitForSingleObject and then after it finishes it acquires 
> dispatcher lock and removes a list item. The problem arises when 
> someone calls KeRemoveQueue just after the KeWaitForSingleObject call 
> finishes and before the dispatcher lock is acquired. In this case he 
> can remove the last item in the list and this will cause the first 
> KeRemoveQueue (the one that waited) to return garbage. Can anybody 
> think of better solution than the attached patch?
>
> Regards,
> Filip
>
>------------------------------------------------------------------------
>
>Index: ntoskrnl/ke/queue.c
>===================================================================
>RCS file: /CVS/ReactOS/reactos/ntoskrnl/ke/queue.c,v
>retrieving revision 1.11
>diff -u -r1.11 queue.c
>--- ntoskrnl/ke/queue.c	15 Aug 2004 16:39:05 -0000	1.11
>+++ ntoskrnl/ke/queue.c	21 Nov 2004 00:39:52 -0000
>@@ -159,27 +159,38 @@
>       return ListEntry;
>    }
> 
>-   //need to wait for it...
>-   KeReleaseDispatcherDatabaseLock (OldIrql);
>-
>-   Status = KeWaitForSingleObject(Queue,
>-                                  WrQueue,
>-                                  WaitMode,
>-                                  TRUE,//Alertable,
>-                                  Timeout);
>-
>-   if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
>-   {
>-      return (PVOID)Status;
>-   }
>-   else
>+   for (;;)
>    {
>-      OldIrql = KeAcquireDispatcherDatabaseLock ();
>-      ListEntry = RemoveHeadList(&Queue->EntryListHead);
>+      //need to wait for it...
>       KeReleaseDispatcherDatabaseLock (OldIrql);
>-      return ListEntry;
>-   }
> 
>+      Status = KeWaitForSingleObject(Queue,
>+                                     WrQueue,
>+                                     WaitMode,
>+                                     TRUE,//Alertable,
>+                                     Timeout);
>+
>+      if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
>+      {
>+         return (PVOID)Status;
>+      }
>+      else
>+      {
>+         OldIrql = KeAcquireDispatcherDatabaseLock ();
>+
>+         /*
>+          * Prevent a race condition. If someone calls KeRemoveQueue
>+          * just after we end up waiting and before acquiring the spin
>+          * lock he can get the last item in the list...
>+          */
>+         if (IsListEmpty(&Queue->EntryListHead))
>+            continue;
>+
>+         ListEntry = RemoveHeadList(&Queue->EntryListHead);
>+         KeReleaseDispatcherDatabaseLock (OldIrql);
>+         return ListEntry;
>+      }
>+   }
> }
> 
> 
>  
>
>------------------------------------------------------------------------
>
>_______________________________________________
>Ros-dev mailing list
>Ros-dev at reactos.com
>http://reactos.com:8080/mailman/listinfo/ros-dev
>  
>



More information about the Ros-dev mailing list