Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp	(revision 35951)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp	(revision 35952)
@@ -76,5 +76,5 @@
 
         /* Mark the stdin buffer as dead; we're not using it anymore. */
-        pStdInBuf->fAlive = false;
+        pStdInBuf->fEnabled = false;
 
         rc2 = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_ERROR);
@@ -113,5 +113,5 @@
         cbToWrite = RT_MIN(cbToWrite, _1M);
         *pfClose = false;
-        if (   pStdInBuf->fAlive
+        if (   pStdInBuf->fEnabled
             && cbToWrite)
         {
@@ -148,5 +148,5 @@
             {
                 *pcbWritten = 0;
-                pStdInBuf->fAlive = pStdInBuf->fAlive;
+                pStdInBuf->fEnabled = pStdInBuf->fEnabled;
             }
 #ifdef DEBUG
@@ -159,9 +159,9 @@
         {
             *pcbWritten = 0;
-            pStdInBuf->fNeedNotification = pStdInBuf->fAlive;
+            pStdInBuf->fNeedNotification = pStdInBuf->fEnabled;
         }
 
         if (   !*pcbWritten
-            && pStdInBuf->fAlive)
+            && pStdInBuf->fEnabled)
         {
             /*
@@ -298,6 +298,6 @@
 #endif
             uint32_t cbWritten;
-            rc = VBoxServiceControlExecWritePipeBuffer(pStdOutBuf, abBuf,
-                                                       cbRead, false /* Pending close */, &cbWritten);
+            rc = VBoxServiceControlExecPipeBufWrite(pStdOutBuf, abBuf,
+                                                    cbRead, false /* Pending close */, &cbWritten);
             if (RT_SUCCESS(rc))
             {
@@ -581,8 +581,12 @@
     if (RT_SUCCESS(rc))
     {
+        VBoxServiceControlExecPipeBufSetStatus(&pData->stdIn, false /* Disabled */);
+        VBoxServiceControlExecPipeBufSetStatus(&pData->stdOut, false /* Disabled */);
+        VBoxServiceControlExecPipeBufSetStatus(&pData->stdErr, false /* Disabled */);
+
         /* Since the process is not alive anymore, destroy its local
          * stdin pipe buffer - it's not used anymore and can eat up quite
          * a bit of memory. */
-        VBoxServiceControlExecDeletePipeBuffer(&pData->stdIn);
+        VBoxServiceControlExecPipeBufDestroy(&pData->stdIn);
 
         uint32_t uStatus = PROC_STS_UNDEFINED;
@@ -710,5 +714,5 @@
  *                                  pipe or not.
  */
-static int VBoxServiceControlExecInitPipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe)
+static int VBoxServiceControlExecPipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe)
 {
     AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER);
@@ -720,44 +724,23 @@
     pBuf->cbSize = 0;
     pBuf->cbOffset = 0;
-    pBuf->fAlive = true;
+    pBuf->fEnabled = true;
     pBuf->fPendingClose = false;
     pBuf->fNeedNotification = fNeedNotificationPipe;
     pBuf->hNotificationPipeW = NIL_RTPIPE;
     pBuf->hNotificationPipeR = NIL_RTPIPE;
-
-    int rc = RTCritSectInit(&pBuf->CritSect);
-    if (RT_SUCCESS(rc) && fNeedNotificationPipe)
-    {
-        rc = RTPipeCreate(&pBuf->hNotificationPipeR, &pBuf->hNotificationPipeW, 0);
-        if (RT_FAILURE(rc))
-            RTCritSectDelete(&pBuf->CritSect);
-    }
-    return rc;
-}
-
-
-/**
- * Deletes a pipe buffer.
- *
- * @param   pBuf            The pipe buffer.
- */
-void VBoxServiceControlExecDeletePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf)
-{
-    AssertPtr(pBuf);
-    if (pBuf->pbData)
-    {
-        RTMemFree(pBuf->pbData);
-        pBuf->pbData = NULL;
-        pBuf->cbAllocated = 0;
-        pBuf->cbSize = 0;
-        pBuf->cbOffset = 0;
-        pBuf->fAlive = false;
-    }
-
-    RTPipeClose(pBuf->hNotificationPipeR);
-    pBuf->hNotificationPipeR = NIL_RTPIPE;
-    RTPipeClose(pBuf->hNotificationPipeW);
-    pBuf->hNotificationPipeW = NIL_RTPIPE;
-    RTCritSectDelete(&pBuf->CritSect);
+    pBuf->hEventSem = NIL_RTSEMEVENT;
+
+    int rc = RTSemEventCreate(&pBuf->hEventSem);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTCritSectInit(&pBuf->CritSect);
+        if (RT_SUCCESS(rc) && fNeedNotificationPipe)
+        {
+            rc = RTPipeCreate(&pBuf->hNotificationPipeR, &pBuf->hNotificationPipeW, 0);
+            if (RT_FAILURE(rc))
+                RTCritSectDelete(&pBuf->CritSect);
+        }
+    }
+    return rc;
 }
 
@@ -773,6 +756,6 @@
  *                                      will reflect the actual amount read on return.
  */
-int VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
-                                                uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead)
+static int VBoxServiceControlExecPipeBufRead(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
+                                             uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead)
 {
     AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER);
@@ -795,4 +778,6 @@
             memcpy(pbBuffer, pBuf->pbData + pBuf->cbOffset, *pcbToRead);
             pBuf->cbOffset += *pcbToRead;
+
+            RTSemEventSignal(pBuf->hEventSem);
         }
         else
@@ -817,7 +802,7 @@
  * @param   pcbWritten                  Pointer to where the amount of written bytes get stored. Optional.
  */
-int VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
-                                          uint8_t *pbData, uint32_t cbData, bool fPendingClose,
-                                          uint32_t *pcbWritten)
+static int VBoxServiceControlExecPipeBufWrite(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
+                                              uint8_t *pbData, uint32_t cbData, bool fPendingClose,
+                                              uint32_t *pcbWritten)
 {
     AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER);
@@ -825,5 +810,5 @@
 
     int rc;
-    if (pBuf->fAlive)
+    if (pBuf->fEnabled)
     {
         rc = RTCritSectEnter(&pBuf->CritSect);
@@ -885,8 +870,4 @@
             if (RT_SUCCESS(rc))
             {
-                /* Report back written bytes (if wanted). */
-                if (pcbWritten)
-                    *pcbWritten = cbData;
-
                 /*
                  * Was this the final read/write to do on this buffer? Then close it
@@ -908,4 +889,10 @@
                     pBuf->fNeedNotification = !RT_SUCCESS(rc2);
                 }
+
+                /* Report back written bytes (if wanted). */
+                if (pcbWritten)
+                    *pcbWritten = cbData;
+
+                RTSemEventSignal(pBuf->hEventSem);
             }
             int rc2 = RTCritSectLeave(&pBuf->CritSect);
@@ -917,4 +904,77 @@
         rc = VERR_BAD_PIPE;
     return rc;
+}
+
+
+/**
+ * Returns whether a pipe buffer is active or not.
+ *
+ * @return  bool            True if pipe buffer is active, false if not.
+ * @param   pBuf            The pipe buffer.
+ */
+static bool VBoxServiceControlExecPipeBufIsEnabled(PVBOXSERVICECTRLEXECPIPEBUF pBuf)
+{
+    AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER);
+
+    bool fEnabled = false;
+    if (RT_SUCCESS(RTCritSectEnter(&pBuf->CritSect)))
+    {
+        fEnabled = pBuf->fEnabled;
+        RTCritSectLeave(&pBuf->CritSect);
+    }
+    return fEnabled;
+}
+
+
+/**
+ * Sets the current status (enabled/disabled) of a pipe buffer.
+ *
+ * @return  IPRT status code.
+ * @param   pBuf            The pipe buffer.
+ * @param   fEnabled        Pipe buffer status to set.
+ */
+static int VBoxServiceControlExecPipeBufSetStatus(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fEnabled)
+{
+    AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER);
+
+    int rc = RTCritSectEnter(&pBuf->CritSect);
+    if (RT_SUCCESS(rc))
+    {
+        pBuf->fEnabled = fEnabled;
+        /* Let waiter know that something has changed ... */
+        if (pBuf->hEventSem)
+            RTSemEventSignal(pBuf->hEventSem);
+        rc = RTCritSectLeave(&pBuf->CritSect);
+    }
+    return rc;
+}
+
+
+/**
+ * Deletes a pipe buffer.
+ * Note: Not thread safe -- only call this when nobody is relying on the
+ *       data anymore!
+ *
+ * @param   pBuf            The pipe buffer.
+ */
+static void VBoxServiceControlExecPipeBufDestroy(PVBOXSERVICECTRLEXECPIPEBUF pBuf)
+{
+    AssertPtr(pBuf);
+    if (pBuf->pbData)
+    {
+        RTMemFree(pBuf->pbData);
+        pBuf->pbData = NULL;
+        pBuf->cbAllocated = 0;
+        pBuf->cbSize = 0;
+        pBuf->cbOffset = 0;
+    }
+
+    RTPipeClose(pBuf->hNotificationPipeR);
+    pBuf->hNotificationPipeR = NIL_RTPIPE;
+    RTPipeClose(pBuf->hNotificationPipeW);
+    pBuf->hNotificationPipeW = NIL_RTPIPE;
+
+    RTSemEventDestroy(pBuf->hEventSem);
+    RTCritSectDelete(&pBuf->CritSect);
 }
 
@@ -1017,10 +1077,10 @@
 
         /* Init buffers. */
-        rc = VBoxServiceControlExecInitPipeBuffer(&pData->stdOut, false /*fNeedNotificationPipe*/);
+        rc = VBoxServiceControlExecPipeBufInit(&pData->stdOut, false /*fNeedNotificationPipe*/);
         if (RT_SUCCESS(rc))
         {
-            rc = VBoxServiceControlExecInitPipeBuffer(&pData->stdErr, false /*fNeedNotificationPipe*/);
+            rc = VBoxServiceControlExecPipeBufInit(&pData->stdErr, false /*fNeedNotificationPipe*/);
             if (RT_SUCCESS(rc))
-                rc = VBoxServiceControlExecInitPipeBuffer(&pData->stdIn, true /*fNeedNotificationPipe*/);
+                rc = VBoxServiceControlExecPipeBufInit(&pData->stdIn, true /*fNeedNotificationPipe*/);
         }
     }
@@ -1059,7 +1119,7 @@
         RTStrFree(pData->pszPassword);
 
-        VBoxServiceControlExecDeletePipeBuffer(&pData->stdOut);
-        VBoxServiceControlExecDeletePipeBuffer(&pData->stdErr);
-        VBoxServiceControlExecDeletePipeBuffer(&pData->stdIn);
+        VBoxServiceControlExecPipeBufDestroy(&pData->stdOut);
+        VBoxServiceControlExecPipeBufDestroy(&pData->stdErr);
+        VBoxServiceControlExecPipeBufDestroy(&pData->stdIn);
 
         RTMemFree(pData);
@@ -1711,5 +1771,6 @@
              */
             uint32_t cbWritten;
-            rc = VBoxServiceControlExecWritePipeBuffer(&pData->stdIn, pabBuffer, cbSize, fPendingClose, &cbWritten);
+            rc = VBoxServiceControlExecPipeBufWrite(&pData->stdIn, pabBuffer,
+                                                    cbSize, fPendingClose, &cbWritten);
 #ifdef DEBUG
             VBoxServiceVerbose(4, "ControlExec: Written to StdIn buffer (PID %u): rc=%Rrc, uFlags=0x%x, cbAlloc=%u, cbSize=%u, cbOffset=%u\n",
@@ -1787,14 +1848,25 @@
             if (pBuf)
             {
-                /** @todo Use uHandleID to distinguish between stdout/stderr! */
-                rc = VBoxServiceControlExecReadPipeBufferContent(&pData->stdOut, pBuf, cbSize, &cbRead);
+                /* If the stdout pipe buffer is enabled (that is, still could be filled by a running
+                 * process) wait for the signal to arrive so that we don't return without any actual
+                 * data read. */
+                if (VBoxServiceControlExecPipeBufIsEnabled(&pData->stdOut))
+                {
+                    VBoxServiceVerbose(4, "ControlExec: Waiting for output data becoming ready ...\n");
+                    rc = RTSemEventWait(pData->stdOut.hEventSem, RT_INDEFINITE_WAIT);
+                }
                 if (RT_SUCCESS(rc))
                 {
-                    /* Note: Since the context ID is unique the request *has* to be completed here,
-                     *       regardless whether we got data or not! Otherwise the progress object
-                     *       on the host never will get completed! */
-                    /* cbRead now contains actual size. */
-                    rc = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, 0 /* Handle ID */, 0 /* Flags */,
-                                                    pBuf, cbRead);
+                    /** @todo Use uHandleID to distinguish between stdout/stderr! */
+                    rc = VBoxServiceControlExecPipeBufRead(&pData->stdOut, pBuf, cbSize, &cbRead);
+                    if (RT_SUCCESS(rc))
+                    {
+                        /* Note: Since the context ID is unique the request *has* to be completed here,
+                         *       regardless whether we got data or not! Otherwise the progress object
+                         *       on the host never will get completed! */
+                        /* cbRead now contains actual size. */
+                        rc = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, 0 /* Handle ID */, 0 /* Flags */,
+                                                        pBuf, cbRead);
+                    }
                 }
                 RTMemFree(pBuf);
Index: /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
===================================================================
--- /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h	(revision 35951)
+++ /trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h	(revision 35952)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2007-2010 Oracle Corporation
+ * Copyright (C) 2007-2011 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -136,6 +136,8 @@
     /** Critical section protecting this buffer structure. */
     RTCRITSECT  CritSect;
-    /** Indicates the health condition of the child process. */
-    bool        fAlive;
+    /** Flag indicating whether this pipe buffer accepts new
+     *  data to be written to or not. If not enabled, already
+     *  (allocated) buffered data still can be read out. */
+    bool        fEnabled;
     /** Set if it's necessary to write to the notification pipe. */
     bool        fNeedNotification;
@@ -147,4 +149,7 @@
     /** The other end of hNotificationPipeW. */
     RTPIPE      hNotificationPipeR;
+    /** The event semaphore for getting notified whether something
+     *  has changed, e.g. written or read from this buffer. */
+    RTSEMEVENT  hEventSem;
 } VBOXSERVICECTRLEXECPIPEBUF;
 /** Pointer to buffered pipe data. */
@@ -299,9 +304,13 @@
                                                   const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS);
 extern void         VBoxServiceControlExecDestroyThreadData(PVBOXSERVICECTRLTHREADDATAEXEC pThread);
-extern void         VBoxServiceControlExecDeletePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf);
-extern int          VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
-                                                                uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead);
-extern int          VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
-                                                          uint8_t *pbData, uint32_t cbData, bool fPendingClose, uint32_t *pcbWritten);
+
+extern int          VBoxServiceControlExecPipeInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe);
+extern int          VBoxServiceControlExecPipeBufRead(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
+                                                      uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead);
+extern int          VBoxServiceControlExecPipeBufWrite(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
+                                                       uint8_t *pbData, uint32_t cbData, bool fPendingClose, uint32_t *pcbWritten);
+extern bool         VBoxServiceControlExecPipeBufIsEnabled(PVBOXSERVICECTRLEXECPIPEBUF pBuf);
+extern int          VBoxServiceControlExecPipeBufSetStatus(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fEnabled);
+extern void         VBoxServiceControlExecPipeBufDestroy(PVBOXSERVICECTRLEXECPIPEBUF pBuf);
 #endif /* VBOX_WITH_GUEST_CONTROL */
 
