Index: trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp
===================================================================
--- trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp	(revision 39428)
+++ trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp	(revision 39434)
@@ -23,4 +23,5 @@
 #include <iprt/assert.h>
 #include <iprt/env.h>
+#include <iprt/file.h>
 #include <iprt/getopt.h>
 #include <iprt/handle.h>
@@ -389,31 +390,11 @@
 {
     int rc = VINF_SUCCESS;
-    if (fPollEvt == RTPOLL_EVT_READ)
-    {
-        /** @todo r=bird: Drop this in favor of using /dev/null
-         * (RTFileOpenBitBucket) instead of pipes. That'll simplify the code,
-         * speed stuff up, avoid trouble is RTPoll is buggy and be
-         * compatible with future wait-for-writeable-stderr/out host
-         * notifications. */
-        char   abBuf[_64K];
-        size_t cbRead;
-        rc = RTPipeRead(*phPipeR, abBuf, sizeof(abBuf), &cbRead);
-        if (RT_SUCCESS(rc) && cbRead)
-        {
-#ifdef DEBUG
-            VBoxServiceVerbose(4, "ControlThread: Drain idPollHnd=%u, abBuf=0x%p, cbRead=%u\n",
-                               idPollHnd, abBuf, cbRead);
-#endif
-            /* Goes to bit bucket ... */
-
-            /* Make sure we go another poll round in case there was too much data
-               for the buffer to hold. */
-            fPollEvt &= RTPOLL_EVT_ERROR;
-        }
-        else if (RT_FAILURE(rc))
-        {
-            fPollEvt |= RTPOLL_EVT_ERROR;
-            AssertMsg(rc == VERR_BROKEN_PIPE, ("%Rrc\n", rc));
-        }
+
+    if (fPollEvt & RTPOLL_EVT_READ)
+    {
+
+        /* Make sure we go another poll round in case there was too much data
+           for the buffer to hold. */
+        fPollEvt &= RTPOLL_EVT_ERROR;
     }
 
@@ -602,5 +583,5 @@
         uint32_t idPollHnd;
         uint32_t fPollEvt;
-        rc2 = RTPollNoResume(hPollSet, /*cMsPollCur*/ RT_INDEFINITE_WAIT, &fPollEvt, &idPollHnd);
+        rc2 = RTPollNoResume(hPollSet, cMsPollCur, &fPollEvt, &idPollHnd);
         if (pThread->fShutdown)
             continue;
@@ -640,9 +621,5 @@
                 break; /* We were asked to shutdown. */
 
-            /* Do we have more to poll for (e.g. is there (still) something in our pollset
-             * like stdout, stderr or stdin)? If we only have our notification pipe left we
-             * need to bail out. */
-            if (RTPollSetGetCount(hPollSet) > 1)
-                continue;
+            continue;
         }
 
@@ -858,4 +835,5 @@
  *
  * @returns IPRT status code.  No client replies made.
+ * @param   pszHowTo            How to set up this standard handle.
  * @param   fd                  Which standard handle it is (0 == stdin, 1 ==
  *                              stdout, 2 == stderr).
@@ -865,37 +843,60 @@
  *                              Always set.
  * @param   phPipe              Where to return the end of the pipe that we
- *                              should service.  Always set.
- *
- * @todo r=bird: Open the bitbucket like txsDoExecHlpRedir does when the host
- *       isn't interested in the guest output.  This is easier to handle
- *       elsewhere.
- */
-static int VBoxServiceControlThreadSetupPipe(int fd, PRTHANDLE ph, PRTHANDLE *pph, PRTPIPE phPipe)
-{
-    AssertPtrReturn(ph, VERR_INVALID_PARAMETER);
-    AssertPtrReturn(pph, VERR_INVALID_PARAMETER);
-    AssertPtrReturn(phPipe, VERR_INVALID_PARAMETER);
+ *                              should service.
+ */
+static int VBoxServiceControlThreadSetupPipe(const char *pszHowTo, int fd,
+                                             PRTHANDLE ph, PRTHANDLE *pph, PRTPIPE phPipe)
+{
+    AssertPtrReturn(ph, VERR_INVALID_POINTER);
+    AssertPtrReturn(ph, VERR_INVALID_POINTER);
+    AssertPtrReturn(pph, VERR_INVALID_POINTER);
 
     int rc;
 
-    /*
-     * Setup a pipe for forwarding to/from the client.
-     * The ph union struct will be filled with a pipe read/write handle
-     * to represent the "other" end to phPipe.
-     */
-    if (fd == 0) /* stdin? */
-    {
-        /* Connect a wrtie pipe specified by phPipe to stdin. */
-        rc = RTPipeCreate(&ph->u.hPipe, phPipe, RTPIPE_C_INHERIT_READ);
-    }
-    else /* stdout or stderr? */
-    {
-        /* Connect a read pipe specified by phPipe to stdout or stderr. */
-        rc = RTPipeCreate(phPipe, &ph->u.hPipe, RTPIPE_C_INHERIT_WRITE);
-    }
-    if (RT_FAILURE(rc))
-        return rc;
     ph->enmType = RTHANDLETYPE_PIPE;
-    *pph = ph;
+    ph->u.hPipe = NIL_RTPIPE;
+    *pph        = NULL;
+    *phPipe     = NIL_RTPIPE;
+
+    if (!strcmp(pszHowTo, "|"))
+    {
+        /*
+         * Setup a pipe for forwarding to/from the client.
+         * The ph union struct will be filled with a pipe read/write handle
+         * to represent the "other" end to phPipe.
+         */
+        if (fd == 0) /* stdin? */
+        {
+            /* Connect a wrtie pipe specified by phPipe to stdin. */
+            rc = RTPipeCreate(&ph->u.hPipe, phPipe, RTPIPE_C_INHERIT_READ);
+        }
+        else /* stdout or stderr? */
+        {
+            /* Connect a read pipe specified by phPipe to stdout or stderr. */
+            rc = RTPipeCreate(phPipe, &ph->u.hPipe, RTPIPE_C_INHERIT_WRITE);
+        }
+
+        if (RT_FAILURE(rc))
+            return rc;
+
+        ph->enmType = RTHANDLETYPE_PIPE;
+        *pph = ph;
+    }
+    else if (!strcmp(pszHowTo, "/dev/null"))
+    {
+        /*
+         * Redirect to/from /dev/null.
+         */
+        RTFILE hFile;
+        rc = RTFileOpenBitBucket(&hFile, fd == 0 ? RTFILE_O_READ : RTFILE_O_WRITE);
+        if (RT_FAILURE(rc))
+            return rc;
+
+        ph->enmType = RTHANDLETYPE_FILE;
+        ph->u.hFile = hFile;
+        *pph = ph;
+    }
+    else /* Add other piping stuff here. */
+        rc = VERR_INVALID_PARAMETER;
 
     return rc;
@@ -1191,5 +1192,6 @@
             RTHANDLE    hStdIn;
             PRTHANDLE   phStdIn;
-            rc = VBoxServiceControlThreadSetupPipe(0 /*STDIN_FILENO*/, &hStdIn, &phStdIn, &pThread->pipeStdInW);
+            rc = VBoxServiceControlThreadSetupPipe("|", 0 /*STDIN_FILENO*/,
+                                                   &hStdIn, &phStdIn, &pThread->pipeStdInW);
             if (RT_SUCCESS(rc))
             {
@@ -1197,5 +1199,8 @@
                 PRTHANDLE   phStdOut;
                 RTPIPE      hStdOutR;
-                rc = VBoxServiceControlThreadSetupPipe(1 /*STDOUT_FILENO*/, &hStdOut, &phStdOut, &hStdOutR);
+                rc = VBoxServiceControlThreadSetupPipe(  (pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDOUT)
+                                                       ? "|" : "/dev/null",
+                                                       1 /*STDOUT_FILENO*/,
+                                                       &hStdOut, &phStdOut, &hStdOutR);
                 if (RT_SUCCESS(rc))
                 {
@@ -1203,5 +1208,8 @@
                     PRTHANDLE   phStdErr;
                     RTPIPE      hStdErrR;
-                    rc = VBoxServiceControlThreadSetupPipe(2 /*STDERR_FILENO*/, &hStdErr, &phStdErr, &hStdErrR);
+                    rc = VBoxServiceControlThreadSetupPipe(  (pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDERR)
+                                                           ? "|" : "/dev/null",
+                                                           2 /*STDERR_FILENO*/,
+                                                           &hStdErr, &phStdErr, &hStdErrR);
                     if (RT_SUCCESS(rc))
                     {
@@ -1219,26 +1227,8 @@
                             /* Stdout. */
                             if (RT_SUCCESS(rc))
-                            {
-                                uint32_t uFlags = RTPOLL_EVT_ERROR;
-                                if (!(pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDOUT))
-                                {
-                                    uFlags |= RTPOLL_EVT_READ;
-                                    VBoxServiceVerbose(3, "ControlThread: Host is not interested in getting stdout for \"%s\", poll flags=0x%x\n",
-                                                        pThread->pszCmd, uFlags);
-                                }
-                                rc = RTPollSetAddPipe(hPollSet, hStdOutR, uFlags, VBOXSERVICECTRLPIPEID_STDOUT);
-                            }
+                                rc = RTPollSetAddPipe(hPollSet, hStdOutR, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDOUT);
                             /* Stderr. */
                             if (RT_SUCCESS(rc))
-                            {
-                                uint32_t uFlags = RTPOLL_EVT_ERROR;
-                                if (!(pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDERR))
-                                {
-                                    uFlags |= RTPOLL_EVT_READ;
-                                    VBoxServiceVerbose(3, "ControlThread: Host is not interested in getting stderr for \"%s\", poll flags=0x%x\n",
-                                                        pThread->pszCmd, uFlags);
-                                }
-                                rc = RTPollSetAddPipe(hPollSet, hStdErrR, uFlags, VBOXSERVICECTRLPIPEID_STDERR);
-                            }
+                                rc = RTPollSetAddPipe(hPollSet, hStdErrR, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDERR);
                             /* IPC notification pipe. */
                             if (RT_SUCCESS(rc))
