Prevent infinite wait in WaitForInputIdle

François Gouget fgouget at codeweavers.com
Sun Oct 7 20:07:28 CDT 2001


   WaitForInputIdle is supposed to time out after a given time. But the
algorithm was:

   while ( dwTimeOut > GetTickCount() - cur_time ...) {
     MsgWaitForMultipleObjects(...dwTimeOut...);
     ...
   }

   So if dwTimeOut is 60 seconds, and a message is received after 59
seconds, then WaitForInputIdle would be stuck in
MsgWaitForMultipleObjects for an extra 60 seconds. Waiting 119 seconds
in all.
   With this patch this should not longer be the case. Other interesting
features: the unsigned int arithmetic, especially wrt. wrap-arounds.
It's a bit weird but should work.


Changelog:

   François Gouget <fgouget at codeweavers.com>

 * windows/message.c
   Better handling of the timeout in WaitForInputIdle
   Use WAIT_FAILED rather than the corresponding literal


-- 
François Gouget
fgouget at codeweavers.com
-------------- next part --------------
Index: windows/message.c
===================================================================
RCS file: /home/wine/wine/windows/message.c,v
retrieving revision 1.125
diff -u -r1.125 message.c
--- windows/message.c	2001/10/02 18:54:00	1.125
+++ windows/message.c	2001/10/07 23:19:57
@@ -743,7 +743,7 @@
  */
 DWORD WINAPI WaitForInputIdle( HANDLE hProcess, DWORD dwTimeOut )
 {
-    DWORD cur_time, ret;
+    DWORD start_time, elapsed, ret;
     HANDLE idle_event = -1;
 
     SERVER_START_REQ( wait_input_idle )
@@ -753,31 +753,37 @@
         if (!(ret = SERVER_CALL_ERR())) idle_event = req->event;
     }
     SERVER_END_REQ;
-    if (ret) return 0xffffffff;  /* error */
+    if (ret) return WAIT_FAILED;  /* error */
     if (!idle_event) return 0;  /* no event to wait on */
 
-    cur_time = GetTickCount();
+    start_time = GetTickCount();
+    elapsed = 0;
 
     TRACE("waiting for %x\n", idle_event );
-    while ( dwTimeOut > GetTickCount() - cur_time || dwTimeOut == INFINITE )
+    do
     {
-        ret = MsgWaitForMultipleObjects ( 1, &idle_event, FALSE, dwTimeOut, QS_SENDMESSAGE );
-        if ( ret == ( WAIT_OBJECT_0 + 1 ))
+        ret = MsgWaitForMultipleObjects ( 1, &idle_event, FALSE, dwTimeOut - elapsed, QS_SENDMESSAGE );
+        switch (ret)
         {
+        case WAIT_OBJECT_0+1:
             process_sent_messages();
-            continue;
-        }
-        if ( ret == WAIT_TIMEOUT || ret == 0xFFFFFFFF )
-        {
+            break;
+        case WAIT_TIMEOUT:
+        case WAIT_FAILED:
             TRACE("timeout or error\n");
             return ret;
-        }
-        else
-        {
+        default:
             TRACE("finished\n");
             return 0;
         }
+        if (dwTimeOut != INFINITE)
+        {
+            elapsed = GetTickCount() - start_time;
+            if (elapsed > dwTimeOut)
+                break;
+        }
     }
+    while (1);
 
     return WAIT_TIMEOUT;
 }


More information about the wine-patches mailing list