Index: /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
===================================================================
--- /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 85565)
+++ /trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp	(revision 85566)
@@ -642,6 +642,8 @@
       , m_hEventSem(NIL_RTSEMEVENT)
       , m_pCurDnD(NULL)
-      , m_fSrvStopping(false)
-    {}
+      , m_fStop(false)
+    {
+        RT_ZERO(m_dndCtx);
+    }
 
     int init(void);
@@ -665,7 +667,10 @@
     RTTHREAD             m_hHGCMThread;
     RTTHREAD             m_hX11Thread;
+    /** This service' DnD command context. */
+    VBGLR3GUESTDNDCMDCTX m_dndCtx;
     RTSEMEVENT           m_hEventSem;
     DragInstance        *m_pCurDnD;
-    bool                 m_fSrvStopping;
+    /** Stop indicator flag to signal the thread that it should shut down. */
+    bool                 m_fStop;
 
     friend class DragInstance;
@@ -3045,22 +3050,21 @@
     {
         rc = RTSemEventCreate(&m_hEventSem);
-        if (RT_FAILURE(rc))
-            break;
+        AssertRCBreak(rc);
 
         rc = RTCritSectInit(&m_eventQueueCS);
-        if (RT_FAILURE(rc))
-            break;
+        AssertRCBreak(rc);
+
+        rc = VbglR3DnDConnect(&m_dndCtx);
+        AssertRCBreak(rc);
 
         /* Event thread for events coming from the HGCM device. */
         rc = RTThreadCreate(&m_hHGCMThread, hgcmEventThread, this,
                             0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, "dndHGCM");
-        if (RT_FAILURE(rc))
-            break;
+        AssertRCBreak(rc);
 
         rc = RTThreadUserWait(m_hHGCMThread, 10 * 1000 /* 10s timeout */);
-        if (RT_FAILURE(rc))
-            break;
-
-        if (ASMAtomicReadBool(&m_fSrvStopping))
+        AssertRCBreak(rc);
+
+        if (ASMAtomicReadBool(&m_fStop))
             break;
 
@@ -3068,17 +3072,15 @@
         rc = RTThreadCreate(&m_hX11Thread, x11EventThread, this,
                             0, RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE, "dndX11");
-        if (RT_FAILURE(rc))
-            break;
+        AssertRCBreak(rc);
 
         rc = RTThreadUserWait(m_hX11Thread, 10 * 1000 /* 10s timeout */);
-        if (RT_FAILURE(rc))
-            break;
-
-        if (ASMAtomicReadBool(&m_fSrvStopping))
+        AssertRCBreak(rc);
+
+        if (ASMAtomicReadBool(&m_fStop))
             break;
 
     } while (0);
 
-    if (m_fSrvStopping)
+    if (m_fStop)
         rc = VERR_GENERAL_FAILURE; /** @todo Fudge! */
 
@@ -3272,5 +3274,5 @@
             XFlush(m_pDisplay);
 
-        } while (!ASMAtomicReadBool(&m_fSrvStopping));
+        } while (!ASMAtomicReadBool(&m_fStop));
 
         VBClLogInfo("Stopped with rc=%Rrc\n", rc);
@@ -3292,7 +3294,11 @@
     LogFlowFuncEnter();
 
-    VBClLogInfo("Terminating threads ...\n");
-
-    ASMAtomicXchgBool(&m_fSrvStopping, true);
+    VBClLogInfo("Terminating ...\n");
+
+    /* Set stop flag first. */
+    ASMAtomicXchgBool(&m_fStop, true);
+
+    /* Disconnect from the HGCM host service, which in turn will make the HGCM thread stop. */
+    VbglR3DnDDisconnect(&m_dndCtx);
 
     /*
@@ -3302,9 +3308,7 @@
     if (m_hHGCMThread != NIL_RTTHREAD)
     {
-#if 0 /** @todo Does not work because we don't cancel the HGCM call! */
+        VBClLogInfo("Terminating HGCM thread ...\n");
+
         rc2 = RTThreadWait(m_hHGCMThread, 30 * 1000 /* 30s timeout */, &rcThread);
-#else
-        rc2 = RTThreadWait(m_hHGCMThread, 200 /* 200ms timeout */, &rcThread);
-#endif
         if (RT_SUCCESS(rc2))
             rc2 = rcThread;
@@ -3316,9 +3320,7 @@
     if (m_hX11Thread != NIL_RTTHREAD)
     {
-#if 0
-        rc2 = RTThreadWait(m_hX11Thread, 30 * 1000 /* 30s timeout */, &rcThread);
-#else
+        VBClLogInfo("Terminating X11 thread ...\n");
+
         rc2 = RTThreadWait(m_hX11Thread, 200 /* 200ms timeout */, &rcThread);
-#endif
         if (RT_SUCCESS(rc2))
             rc2 = rcThread;
@@ -3349,24 +3351,8 @@
     AssertPtrReturn(pvUser, VERR_INVALID_PARAMETER);
     DragAndDropService *pThis = static_cast<DragAndDropService*>(pvUser);
-    AssertPtr(pThis);
-
-    /* This thread has an own DnD context, e.g. an own client ID. */
-    VBGLR3GUESTDNDCMDCTX dndCtx;
-
-    /*
-     * Initialize thread.
-     */
-    int rc = VbglR3DnDConnect(&dndCtx);
-
-    /* Set stop indicator on failure. */
-    if (RT_FAILURE(rc))
-        ASMAtomicXchgBool(&pThis->m_fSrvStopping, true);
 
     /* Let the service instance know in any case. */
-    int rc2 = RTThreadUserSignal(hThread);
-    AssertRC(rc2);
-
-    if (RT_FAILURE(rc))
-        return rc;
+    int rc = RTThreadUserSignal(hThread);
+    AssertRCReturn(rc, rc);
 
     /* Number of invalid messages skipped in a row. */
@@ -3380,5 +3366,5 @@
 
         /* Wait for new events. */
-        rc = VbglR3DnDEventGetNext(&dndCtx, &e.hgcm);
+        rc = VbglR3DnDEventGetNext(&pThis->m_dndCtx, &e.hgcm);
         if (RT_SUCCESS(rc))
         {
@@ -3392,19 +3378,24 @@
         else
         {
-            VBClLogError("Processing next message failed with rc=%Rrc\n", rc);
-
-            /* Old(er) hosts either are broken regarding DnD support or otherwise
-             * don't support the stuff we do on the guest side, so make sure we
-             * don't process invalid messages forever. */
-            if (cMsgSkippedInvalid++ > 32)
+            if (rc == VERR_INTERRUPTED) /* Can happen due to disconnect, for instance. */
+                rc = VINF_SUCCESS;
+
+            if (RT_FAILURE(rc))
             {
-                VBClLogError("Too many invalid/skipped messages from host, exiting ...\n");
-                break;
+                VBClLogError("Processing next message failed with rc=%Rrc\n", rc);
+
+                /* Old(er) hosts either are broken regarding DnD support or otherwise
+                 * don't support the stuff we do on the guest side, so make sure we
+                 * don't process invalid messages forever. */
+
+                if (cMsgSkippedInvalid++ > 32)
+                {
+                    VBClLogError("Too many invalid/skipped messages from host, exiting ...\n");
+                    break;
+                }
             }
         }
 
-    } while (!ASMAtomicReadBool(&pThis->m_fSrvStopping));
-
-    VbglR3DnDDisconnect(&dndCtx);
+    } while (!ASMAtomicReadBool(&pThis->m_fStop));
 
     LogFlowFuncLeaveRC(rc);
@@ -3433,5 +3424,5 @@
     /* Set stop indicator on failure. */
     if (RT_FAILURE(rc))
-        ASMAtomicXchgBool(&pThis->m_fSrvStopping, true);
+        ASMAtomicXchgBool(&pThis->m_fStop, true);
 
     /* Let the service instance know in any case. */
@@ -3485,5 +3476,5 @@
             RTThreadSleep(25 /* ms */);
 
-    } while (!ASMAtomicReadBool(&pThis->m_fSrvStopping));
+    } while (!ASMAtomicReadBool(&pThis->m_fStop));
 
     LogFlowFuncLeaveRC(rc);
