Index: /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxIPC.cpp
===================================================================
--- /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxIPC.cpp	(revision 50038)
+++ /trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxIPC.cpp	(revision 50039)
@@ -7,5 +7,5 @@
 
 /*
- * Copyright (C) 2010-2013 Oracle Corporation
+ * Copyright (C) 2010-2014 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -78,5 +78,5 @@
 static PFNGETLASTINPUTINFO s_pfnGetLastInputInfo = NULL;
 
-int vboxIPCSessionDestroyLocked(PVBOXIPCSESSION pSession);
+int vboxIPCSessionStop(PVBOXIPCSESSION pSession);
 
 static int vboxIPCHandleVBoxTrayRestart(PVBOXIPCSESSION pSession, PVBOXTRAYIPCHEADER pHdr)
@@ -231,4 +231,5 @@
     LogFunc(("Stopping pInstance=%p\n", pInstance));
 
+    /* Shut down local IPC server. */
     PVBOXIPCCONTEXT pCtx = (PVBOXIPCCONTEXT)pInstance;
     AssertPtr(pCtx);
@@ -240,10 +241,27 @@
             LogFunc(("Cancelling current listening call failed with rc=%Rrc\n", rc2));
     }
+
+    /* Stop all remaining session threads. */
+    int rc = RTCritSectEnter(&pCtx->CritSect);
+    if (RT_SUCCESS(rc))
+    {
+        PVBOXIPCSESSION pSession;
+        RTListForEach(&pCtx->SessionList, pSession, VBOXIPCSESSION, Node)
+        {
+            int rc2 = vboxIPCSessionStop(pSession);
+            if (RT_FAILURE(rc2))
+            {
+                LogFunc(("Stopping IPC session %p failed with rc=%Rrc\n",
+                         pSession, rc2));
+                /* Keep going. */
+            }
+        }
+    }
 }
 
 void VBoxIPCDestroy(const VBOXSERVICEENV *pEnv, void *pInstance)
 {
-    AssertPtr(pEnv);
-    AssertPtr(pInstance);
+    AssertPtrReturnVoid(pEnv);
+    AssertPtrReturnVoid(pInstance);
 
     LogFunc(("Destroying pInstance=%p\n", pInstance));
@@ -252,27 +270,43 @@
     AssertPtr(pCtx);
 
+    /* Shut down local IPC server. */
     int rc = RTCritSectEnter(&pCtx->CritSect);
     if (RT_SUCCESS(rc))
     {
-        PVBOXIPCSESSION pSession;
-        RTListForEach(&pCtx->SessionList, pSession, VBOXIPCSESSION, Node)
-        {
-            int rc2 = vboxIPCSessionDestroyLocked(pSession);
-            if (RT_FAILURE(rc2))
-            {
-                LogFunc(("Destroying IPC session %p failed with rc=%Rrc\n",
-                         pSession, rc2));
-                /* Keep going. */
-            }
-        }
-
-        RTLocalIpcServerDestroy(pCtx->hServer);
+        rc = RTLocalIpcServerDestroy(pCtx->hServer);
+        if (RT_FAILURE(rc))
+            LogFunc(("Unable to destroy IPC server, rc=%Rrc\n", rc));
 
         int rc2 = RTCritSectLeave(&pCtx->CritSect);
-        AssertRC(rc2);
-
-        rc2 = RTCritSectDelete(&pCtx->CritSect);
-        AssertRC(rc2);
-    }
+        if (RT_SUCCESS(rc))
+            rc = rc2;
+    }
+
+    LogFunc(("Waiting for remaining IPC sessions to shut down ...\n"));
+
+    /* Wait for all IPC session threads to shut down. */
+    bool fListIsEmpty = true;
+    do
+    {
+        int rc2 = RTCritSectEnter(&pCtx->CritSect);
+        if (RT_SUCCESS(rc2))
+        {
+            fListIsEmpty = RTListIsEmpty(&pCtx->SessionList);
+            rc2 = RTCritSectLeave(&pCtx->CritSect);
+        }
+
+        if (RT_FAILURE(rc2))
+            break;
+
+    } while (!fListIsEmpty);
+
+    AssertMsg(fListIsEmpty,
+              ("Session thread list is not empty when it should\n"));
+
+    LogFunc(("All remaining IPC sessions shut down\n"));
+
+    int rc2 = RTCritSectDelete(&pCtx->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
 
     LogFunc(("Destroyed pInstance=%p, rc=%Rrc\n",
@@ -390,19 +424,32 @@
 
     /*
+     * Close the session.
+     */
+    int rc2 = RTLocalIpcSessionClose(hSession);
+    if (RT_FAILURE(rc2))
+        LogFunc(("Session %p: Failed closing session %p, rc=%Rrc\n", pThis, rc2));
+
+    /*
      * Clean up the session.
      */
     PVBOXIPCCONTEXT pCtx = ASMAtomicReadPtrT(&pThis->pCtx, PVBOXIPCCONTEXT);
     AssertMsg(pCtx, ("Session %p: No context found\n", pThis));
-    rc = RTCritSectEnter(&pCtx->CritSect);
-    if (RT_SUCCESS(rc))
-    {
-        rc = vboxIPCSessionDestroyLocked(pThis);
-
-        int rc2 = RTCritSectLeave(&pCtx->CritSect);
+    rc2 = RTCritSectEnter(&pCtx->CritSect);
+    if (RT_SUCCESS(rc2))
+    {
+        /* Remove this session from the session list. */
+        RTListNodeRemove(&pThis->Node);
+
+        rc2 = RTCritSectLeave(&pCtx->CritSect);
         if (RT_SUCCESS(rc))
             rc = rc2;
     }
 
-    LogFunc(("Session %p: Terminated\n", pThis));
+    LogFunc(("Session %p: Terminated with rc=%Rrc, freeing ...\n",
+             pThis, rc));
+
+    RTMemFree(pThis);
+    pThis = NULL;
+
     return rc;
 }
@@ -426,6 +473,7 @@
             /* Start IPC session thread. */
             LogFlowFunc(("Creating thread for session %p ...\n", pSession));
-            rc = RTThreadCreate(&pSession->hThread, vboxIPCSessionThread, pSession, 0,
-                                RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "VBXTRYIPCSESS");
+            rc = RTThreadCreate(&pSession->hThread, vboxIPCSessionThread,
+                                pSession /* pvUser */, 0 /* Default stack size */,
+                                RTTHREADTYPE_DEFAULT, 0 /* Flags */, "VBXTRYIPCSESS");
             if (RT_SUCCESS(rc))
             {
@@ -453,20 +501,16 @@
 }
 
-static int vboxIPCSessionDestroyLocked(PVBOXIPCSESSION pSession)
+static int vboxIPCSessionStop(PVBOXIPCSESSION pSession)
 {
     AssertPtrReturn(pSession, VERR_INVALID_POINTER);
 
-    pSession->hThread = NIL_RTTHREAD;
+    ASMAtomicWriteBool(&pSession->fTerminate, true);
 
     RTLOCALIPCSESSION hSession;
     ASMAtomicXchgHandle(&pSession->hSession, NIL_RTLOCALIPCSESSION, &hSession);
-    int rc = RTLocalIpcSessionClose(hSession);
-
-    RTListNodeRemove(&pSession->Node);
-
-    RTMemFree(pSession);
-    pSession = NULL;
-
-    return rc;
+    if (hSession)
+        return RTLocalIpcSessionClose(hSession);
+
+    return VINF_SUCCESS;
 }
 
