From ba7f6c541fc406179427ffc912551722d8c5e8ff Mon Sep 17 00:00:00 2001
From: Francois Gouget <fgouget@codeweavers.com>
Date: Mon, 8 Oct 2001 20:28:36 +0000
Subject: [PATCH] Fix infinite loop problem in wineclipsrv startup.
 LaunchServer: Don't give up on the first message. Added GetSelectionEvent:
 Limit CPU use and introduce timeout.

---
 windows/x11drv/clipboard.c   | 16 ++++++++++++-
 windows/x11drv/wineclipsrv.c | 46 ++++++++++++++++++++++++++----------
 2 files changed, 49 insertions(+), 13 deletions(-)

diff --git a/windows/x11drv/clipboard.c b/windows/x11drv/clipboard.c
index 43d4de8f791..cdc7670461a 100644
--- a/windows/x11drv/clipboard.c
+++ b/windows/x11drv/clipboard.c
@@ -295,10 +295,24 @@ BOOL X11DRV_CLIPBOARD_LaunchServer()
     else
     {
         /* Wait until we lose the selection, timing out after a minute */
+        DWORD start_time, timeout, elapsed, ret;
 
         TRACE("Waiting for clipboard server to acquire selection\n");
 
-        if ( MsgWaitForMultipleObjects( 1, &selectionClearEvent, FALSE, 60000, QS_ALLINPUT ) != WAIT_OBJECT_0 )
+        timeout = 60000;
+        start_time = GetTickCount();
+        elapsed=0;
+        do
+        {
+            ret = MsgWaitForMultipleObjects( 1, &selectionClearEvent, FALSE, timeout - elapsed, QS_ALLINPUT );
+            if (ret != WAIT_OBJECT_0+1)
+                break;
+            elapsed = GetTickCount() - start_time;
+            if (elapsed > timeout)
+                break;
+        }
+        while (1);
+        if ( ret != WAIT_OBJECT_0 )
             TRACE("Server could not acquire selection, or a timeout occurred!\n");
         else
             TRACE("Server successfully acquired selection\n");
diff --git a/windows/x11drv/wineclipsrv.c b/windows/x11drv/wineclipsrv.c
index 5e0b938bef8..662c85da771 100644
--- a/windows/x11drv/wineclipsrv.c
+++ b/windows/x11drv/wineclipsrv.c
@@ -415,6 +415,36 @@ int AcquireSelection()
     return g_selectionAcquired;
 }
 
+BOOL GetSelectionEvent(Atom SelectionSrc, XEvent *xe)
+{
+    time_t end_time;
+
+    /* Set up a 10 second time out */
+    end_time=time(NULL)+10;
+
+    do
+    {
+        struct timeval nap;
+
+        if (XCheckTypedWindowEvent(g_display, g_win, SelectionNotify, xe))
+        {
+            if( xe->xselection.selection == SelectionSrc )
+                return TRUE;
+        }
+
+        if (time(NULL)>end_time)
+            break;
+
+        /* Sleep a bit to make this busy wait less brutal */
+        nap.tv_sec = 0;
+        nap.tv_usec = 10;
+        select(0, NULL, NULL, NULL, &nap);
+    }
+    while (TRUE);
+
+    return FALSE;
+}
+
 /**************************************************************************
  *		CacheDataFormats
  *
@@ -457,12 +487,8 @@ int CacheDataFormats( Atom SelectionSrc, PCACHEENTRY *ppCache )
     /*
      * Wait until SelectionNotify is received
      */
-    while( TRUE )
-    {
-       if( XCheckTypedWindowEvent(g_display, g_win, SelectionNotify, &xe) )
-           if( xe.xselection.selection == SelectionSrc )
-               break;
-    }
+    if (!GetSelectionEvent(SelectionSrc, &xe))
+        return 0;
 
     /* Verify that the selection returned a valid TARGETS property */
     if ( (xe.xselection.target != aTargets)
@@ -541,12 +567,8 @@ BOOL FillCacheEntry( Atom SelectionSrc, Atom target, PCACHEENTRY pCacheEntry )
                     g_win, CurrentTime);
 
     /* wait until SelectionNotify is received */
-    while( TRUE )
-    {
-       if( XCheckTypedWindowEvent(g_display, g_win, SelectionNotify, &xe) )
-           if( xe.xselection.selection == SelectionSrc )
-               break;
-    }
+    if (!GetSelectionEvent(SelectionSrc,&xe))
+        return bRet;
 
     /* Now proceed to retrieve the actual converted property from
      * the SELECTION_DATA atom */
-- 
GitLab