Index: /trunk/include/VBox/HostServices/GuestControlSvc.h
===================================================================
--- /trunk/include/VBox/HostServices/GuestControlSvc.h	(revision 29437)
+++ /trunk/include/VBox/HostServices/GuestControlSvc.h	(revision 29438)
@@ -136,14 +136,14 @@
      * or starting a program.
      */
-    HOST_EXEC_CMD = 1,
+    HOST_EXEC_CMD = 100,
     /**
      * Sends input data for stdin to a running process executed by HOST_EXEC_CMD.
      */
-    HOST_EXEC_SET_INPUT = 2,
+    HOST_EXEC_SET_INPUT = 101,
     /**
      * Gets the current status of a running process, e.g.
      * new data on stdout/stderr, process terminated etc.
      */
-    HOST_EXEC_GET_OUTPUT = 3
+    HOST_EXEC_GET_OUTPUT = 102
 };
 
@@ -155,15 +155,22 @@
 {
     /**
+     * Guest waits for a new message the host wants to process on the guest side.
+     * This is a blocking call and can be deferred.
+     */
+    GUEST_GET_HOST_MSG = 1,
+    /**
+     * Guest asks the host to cancel all pending waits the guest waits on.
+     * This becomes necessary when the guest wants to quit but still waits for
+     * commands from the host.
+     */
+    GUEST_CANCEL_PENDING_WAITS = 2,
+    /**
      * TODO
      */
-    GUEST_GET_HOST_MSG = 1,
+    GUEST_EXEC_SEND_OUTPUT = 100,
     /**
      * TODO
      */
-    GUEST_EXEC_SEND_OUTPUT = 2,
-    /**
-     * TODO
-     */
-    GUEST_EXEC_SEND_STATUS = 3
+    GUEST_EXEC_SEND_STATUS = 101
 };
 
@@ -175,17 +182,21 @@
 {
     /**
+     * Hosts wants the guest to stop waiting for new messages.
+     */
+    GETHOSTMSG_EXEC_HOST_CANCEL_WAIT = 0,
+    /**
      * The host wants to execute something in the guest. This can be a command line
      * or starting a program.
      */
-    GETHOSTMSG_EXEC_START_PROCESS = 1,
+    GETHOSTMSG_EXEC_START_PROCESS = 100,
     /**
      * Sends input data for stdin to a running process executed by HOST_EXEC_CMD.
      */
-    GETHOSTMSG_EXEC_SEND_INPUT = 2,
+    GETHOSTMSG_EXEC_SEND_INPUT = 101,
     /**
      * Host requests the so far collected stdout/stderr output
      * from a running process executed by HOST_EXEC_CMD.
      */
-    GETHOSTMSG_EXEC_GET_OUTPUT = 3
+    GETHOSTMSG_EXEC_GET_OUTPUT = 102
 };
 
@@ -200,11 +211,16 @@
     /**
      * The returned command the host wants to
-     * execute on the guest.
+     * run on the guest.
      */
     HGCMFunctionParameter msg;       /* OUT uint32_t */
-
+    /** Number of parameters the message needs. */
     HGCMFunctionParameter num_parms; /* OUT uint32_t */
 
 } VBoxGuestCtrlHGCMMsgType;
+
+typedef struct _VBoxGuestCtrlHGCMMsgCancelPendingWaits
+{
+    VBoxGuestHGCMCallInfo hdr;
+} VBoxGuestCtrlHGCMMsgCancelPendingWaits;
 
 typedef struct _VBoxGuestCtrlHGCMMsgExecCmd
Index: /trunk/include/VBox/VBoxGuestLib.h
===================================================================
--- /trunk/include/VBox/VBoxGuestLib.h	(revision 29437)
+++ /trunk/include/VBox/VBoxGuestLib.h	(revision 29438)
@@ -509,5 +509,6 @@
 VBGLR3DECL(int)     VbglR3GuestCtrlConnect(uint32_t *pu32ClientId);
 VBGLR3DECL(int)     VbglR3GuestCtrlDisconnect(uint32_t u32ClientId);
-VBGLR3DECL(int)     VbglR3GuestCtrlGetHostMsg(uint32_t u32ClientId, uint32_t *puMsg, uint32_t *puNumParms, uint32_t u32Timeout);
+VBGLR3DECL(int)     VbglR3GuestCtrlGetHostMsg(uint32_t u32ClientId, uint32_t *puMsg, uint32_t *puNumParms);
+VBGLR3DECL(int)     VbglR3GuestCtrlCancelPendingWaits(uint32_t u32ClientId);
 VBGLR3DECL(int)     VbglR3GuestCtrlExecGetHostCmd(uint32_t  u32ClientId,    uint32_t  uNumParms,
                                                   uint32_t *puContext,
Index: /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestCtrl.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestCtrl.cpp	(revision 29437)
+++ /trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibGuestCtrl.cpp	(revision 29438)
@@ -103,5 +103,5 @@
  *                          in a second call to the host.
  */
-VBGLR3DECL(int) VbglR3GuestCtrlGetHostMsg(uint32_t u32ClientId, uint32_t *puMsg, uint32_t *puNumParms, uint32_t u32Timeout)
+VBGLR3DECL(int) VbglR3GuestCtrlGetHostMsg(uint32_t u32ClientId, uint32_t *puMsg, uint32_t *puNumParms)
 {
     AssertPtr(puMsg);
@@ -127,4 +127,30 @@
                 rc = Msg.hdr.result;
                 /* Ok, so now we know what message type and how much parameters there are. */
+    }
+    return rc;
+}
+
+
+/**
+ * Asks the host to cancel (release) all pending waits which were deferred.
+ *
+ * @returns VBox status code.
+ * @param   u32ClientId     The client id returned by VbglR3GuestCtrlConnect().
+ */
+VBGLR3DECL(int) VbglR3GuestCtrlCancelPendingWaits(uint32_t u32ClientId)
+{
+    VBoxGuestCtrlHGCMMsgCancelPendingWaits Msg;
+
+    Msg.hdr.result = VERR_WRONG_ORDER;
+    Msg.hdr.u32ClientID = u32ClientId;
+    Msg.hdr.u32Function = GUEST_CANCEL_PENDING_WAITS;
+    Msg.hdr.cParms = 0;
+
+    int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg));
+    if (RT_SUCCESS(rc))
+    {
+        int rc2 = Msg.hdr.result;
+        if (RT_FAILURE(rc2))
+            rc = rc2;
     }
     return rc;
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp	(revision 29437)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp	(revision 29438)
@@ -358,8 +358,9 @@
         VBoxServiceVerbose(1, "Starting '%s' in the main thread\n", g_aServices[iMain].pDesc->pszName);
         rc = g_aServices[iMain].pDesc->pfnWorker(&g_fShutdown);
-        if (rc != VINF_SUCCESS) /* Only complain if service returned an error. Otherwise the service is a one-timer. */
-        {
-            VBoxServiceError("Service '%s' stopped unexpected; rc=%Rrc\n", g_aServices[iMain].pDesc->pszName, rc);
-        }
+        if (RT_SUCCESS(rc))
+            VBoxServiceVerbose(1, "Main service '%s' successfully stopped.\n", g_aServices[iMain].pDesc->pszName);
+        else /* Only complain if service returned an error. Otherwise the service is a one-timer. */
+            VBoxServiceError("Service '%s' stopped unexpected; rc=%Rrc\n", g_aServices[iMain].pDesc->pszName, rc);           
+        g_aServices[iMain].pDesc->pfnTerm();
     }
     return rc;
@@ -376,4 +377,5 @@
 {
     int rc = VINF_SUCCESS;
+    int iMain = VBoxServiceGetStartedServices();
 
     for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
@@ -381,7 +383,16 @@
     for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
         if (g_aServices[j].fStarted)
+        {
+            VBoxServiceVerbose(3, "Calling stop function for service '%s' ...\n", g_aServices[j].pDesc->pszName);
             g_aServices[j].pDesc->pfnStop();
-    for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
-        if (g_aServices[j].fEnabled)
+        }
+    for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
+
+        if (    !g_aServices[j].fEnabled /* Only stop services which were started before. */
+            ||  j == iMain)              /* Don't call the termination function for main service yet. */
+        {
+            continue;
+        }
+        else
         {
             if (g_aServices[j].Thread != NIL_RTTHREAD)
@@ -405,4 +416,20 @@
         }
 
+#ifdef RT_OS_WINDOWS
+    /* 
+     * As we're now done terminating all service threads, 
+     * we have to stop the main thread as well (if defined). Note that the termination
+     * function will be called in a later context (when the main thread returns from the worker
+     * function).
+     */
+    if (iMain != ~0U)
+    {
+        VBoxServiceVerbose(3, "Stopping main service '%s' (%d) ...\n", g_aServices[iMain].pDesc->pszName, iMain);
+
+        ASMAtomicXchgBool(&g_fShutdown, true);
+        g_aServices[iMain].pDesc->pfnStop();                      
+    }
+#endif
+    
     VBoxServiceVerbose(2, "Stopping services returned: rc=%Rrc\n", rc);
     return rc;
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp	(revision 29437)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp	(revision 29438)
@@ -247,5 +247,5 @@
         uint32_t uNumParms;
         VBoxServiceVerbose(3, "Control: Waiting for host msg ...\n");
-        rc = VbglR3GuestCtrlGetHostMsg(g_GuestControlSvcClientID, &uMsg, &uNumParms, 1000 /* 1s timeout */);
+        rc = VbglR3GuestCtrlGetHostMsg(g_GuestControlSvcClientID, &uMsg, &uNumParms);
         if (RT_FAILURE(rc))
         {
@@ -264,4 +264,8 @@
             switch(uMsg)
             {
+                case GETHOSTMSG_EXEC_HOST_CANCEL_WAIT:
+                    VBoxServiceVerbose(3, "Control: Host asked us to quit ...\n");
+                    break;
+
                 case GETHOSTMSG_EXEC_START_PROCESS:
                     rc = VBoxServiceControlHandleCmdStartProcess(g_GuestControlSvcClientID, uNumParms);
@@ -283,7 +287,8 @@
 
         /* Do we need to shutdown? */
-        if (*pfShutdown)
-        {
-            rc = 0;
+        if (   *pfShutdown
+            || uMsg == GETHOSTMSG_EXEC_HOST_CANCEL_WAIT)
+        {
+            rc = VINF_SUCCESS;
             break;
         }
@@ -302,7 +307,20 @@
 static DECLCALLBACK(void) VBoxServiceControlStop(void)
 {
+    VBoxServiceVerbose(3, "Control: Stopping ...\n");
+
     /** @todo Later, figure what to do if we're in RTProcWait(). it's a very
      *        annoying call since doesn't support timeouts in the posix world. */
     RTSemEventMultiSignal(g_hControlEvent);
+
+    /*
+     * Ask the host service to cancel all pending requests so that we can
+     * shutdown properly here. 
+     */
+    if (g_GuestControlSvcClientID)
+    {
+        int rc = VbglR3GuestCtrlCancelPendingWaits(g_GuestControlSvcClientID);
+        if (RT_FAILURE(rc))
+            VBoxServiceError("Control: Cancelling pending waits failed; rc=%Rrc\n", rc);
+    }
 }
 
@@ -311,4 +329,6 @@
 static DECLCALLBACK(void) VBoxServiceControlTerm(void)
 {
+    VBoxServiceVerbose(3, "Control: Terminating ...\n");
+
     /* Signal all threads that we want to shutdown. */
     PVBOXSERVICECTRLTHREAD pNode;
@@ -321,4 +341,5 @@
         if (pNode->Thread != NIL_RTTHREAD)
         {
+            /* Wait a bit ... */
             int rc2 = RTThreadWait(pNode->Thread, 30 * 1000 /* Wait 30 seconds max. */, NULL);
             if (RT_FAILURE(rc2))
Index: /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 29437)
+++ /trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp	(revision 29438)
@@ -318,8 +318,8 @@
                         if (verbose)
                             RTPrintf("No time left to wait for process!\n");
-                    }                    
+                    }
                 }
                 else if (verbose)
-                    RTPrintf("Waiting for process to exit ...\n");                        
+                    RTPrintf("Waiting for process to exit ...\n");
 
                 /* setup signal handling if cancelable */
@@ -344,9 +344,9 @@
                 while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted))))
                 {
-                    /* 
+                    /*
                      * because we want to get all the output data even if the process
                      * already ended, we first need to check whether there is some data
                      * left to output before checking the actual timeout and is-process-completed
-                     * stuff. 
+                     * stuff.
                      */
                     if (cbOutputData <= 0)
@@ -363,8 +363,8 @@
                     }
 
-                    if (   waitForStdOut 
+                    if (   waitForStdOut
                         || waitForStdErr)
                     {
-                        CHECK_ERROR_BREAK(guest, GetProcessOutput(uPID, 0 /* aFlags */, 
+                        CHECK_ERROR_BREAK(guest, GetProcessOutput(uPID, 0 /* aFlags */,
                                                                   u32TimeoutMS, _64K, ComSafeArrayAsOutParam(aOutputData)));
                         cbOutputData = aOutputData.size();
@@ -421,5 +421,5 @@
                 }
                 else
-                {                   
+                {
                     if (fCompleted)
                     {
@@ -440,9 +440,5 @@
                             CHECK_ERROR_BREAK(guest, GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &uRetStatus));
                             RTPrintf("Exit code=%u (Status=%u, Flags=%u)\n", uRetExitCode, uRetStatus, uRetFlags);
-                        }       
-                    }
-                    else /* not completed yet? -> timeout */
-                    {
-                        RTPrintf("Process timed out!\n");
+                        }
                     }
                 }
Index: /trunk/src/VBox/HostServices/GuestControl/service.cpp
===================================================================
--- /trunk/src/VBox/HostServices/GuestControl/service.cpp	(revision 29437)
+++ /trunk/src/VBox/HostServices/GuestControl/service.cpp	(revision 29438)
@@ -220,4 +220,5 @@
     int sendHostCmdToGuest(HostCmd *pCmd, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     int retrieveNextHostCmd(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
+    int cancelPendingWaits(uint32_t u32ClientID);
     int notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
     int processHostCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
@@ -443,4 +444,27 @@
 }
 
+int Service::cancelPendingWaits(uint32_t u32ClientID)
+{
+    int rc = VINF_SUCCESS;
+    CallListIter it = mClientList.begin();
+    while (it != mClientList.end())
+    {
+        if (it->mClientID == u32ClientID)
+        {       
+            if (it->mNumParms >= 2)
+            {
+                it->mParms[0].setUInt32(GETHOSTMSG_EXEC_HOST_CANCEL_WAIT); /* Message ID */
+                it->mParms[1].setUInt32(0);                                /* Required parameters for message */
+            }              
+            if (mpHelpers)
+                mpHelpers->pfnCallComplete(it->mHandle, rc);      
+            it = mClientList.erase(it);
+        }
+        else
+            it++;
+    }
+    return rc;
+}
+
 int Service::notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
 {
@@ -503,4 +527,5 @@
 
             /* In any case the client did something, so wake up and remove from list. */
+            AssertPtr(mpHelpers);
             mpHelpers->pfnCallComplete(guest.mHandle, rc);
             mClientList.pop_front();                       
@@ -559,4 +584,9 @@
                 break;
 
+            case GUEST_CANCEL_PENDING_WAITS:
+                LogFlowFunc(("GUEST_CANCEL_PENDING_WAITS\n"));
+                rc = cancelPendingWaits(u32ClientID);
+                break;
+
             /* The guest notifies the host that some output at stdout/stderr is available. */
             case GUEST_EXEC_SEND_OUTPUT:
@@ -578,4 +608,5 @@
         {
             /* Tell the client that the call is complete (unblocks waiting). */
+            AssertPtr(mpHelpers);
             mpHelpers->pfnCallComplete(callHandle, rc);
         }
