Index: trunk/src/VBox/Main/GuestImpl.cpp
===================================================================
--- trunk/src/VBox/Main/GuestImpl.cpp	(revision 28625)
+++ trunk/src/VBox/Main/GuestImpl.cpp	(revision 28626)
@@ -979,7 +979,9 @@
     paParms[i++].setUInt32(aPID);
     paParms[i++].setUInt32(aFlags); /** @todo Should represent stdout and/or stderr. */
-    //paParms[i++].setPointer(outputData.raw(), aSize);
 
     int vrc = VINF_SUCCESS;
+
+    /* Make sure mParent is valid, so set a read lock in this scope. */
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
 
     /* Forward the information to the VMM device. */
@@ -992,4 +994,6 @@
                                    i, paParms);
     }
+
+    alock.release();
 
     if (RT_SUCCESS(vrc))
@@ -1003,39 +1007,48 @@
          */
         CallbackListIter it = getCtrlCallbackContextByID(uContextID);
-        uint64_t u64Started = RTTimeMilliTS();
-        do
-        {
-            unsigned cMsWait;
-            if (aTimeoutMS == RT_INDEFINITE_WAIT)
-                cMsWait = 1000;
+        if (it != mCallbackList.end())
+        {
+            uint64_t u64Started = RTTimeMilliTS();
+            do
+            {
+                unsigned cMsWait;
+                if (aTimeoutMS == RT_INDEFINITE_WAIT)
+                    cMsWait = 1000;
+                else
+                {
+                    uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
+                    if (cMsElapsed >= aTimeoutMS)
+                        break; /* timed out */
+                    cMsWait = RT_MIN(1000, aTimeoutMS - (uint32_t)cMsElapsed);
+                }
+                RTThreadSleep(100);
+            } while (!it->bCalled);
+
+            AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+            /* Did we get some output? */
+            PHOSTEXECOUTCALLBACKDATA pData = (HOSTEXECOUTCALLBACKDATA*)it->pvData;
+            Assert(it->cbData == sizeof(HOSTEXECOUTCALLBACKDATA));
+            AssertPtr(pData);
+    
+            if (   it->bCalled
+                && pData->cbData)
+            {
+                /* Do we need to resize the array? */
+                if (pData->cbData > cbData)
+                    outputData.resize(pData->cbData);
+    
+                /* Fill output in supplied out buffer. */
+                memcpy(outputData.raw(), pData->pvData, pData->cbData);
+                outputData.resize(pData->cbData); /* Shrink to fit actual buffer size. */
+            }
             else
-            {
-                uint64_t cMsElapsed = RTTimeMilliTS() - u64Started;
-                if (cMsElapsed >= aTimeoutMS)
-                    break; /* timed out */
-                cMsWait = RT_MIN(1000, aTimeoutMS - (uint32_t)cMsElapsed);
-            }
-            RTThreadSleep(100);
-        } while (it != mCallbackList.end() && !it->bCalled);
-
-        /* Did we get some output? */
-        PHOSTEXECOUTCALLBACKDATA pData = (HOSTEXECOUTCALLBACKDATA*)it->pvData;
-        Assert(it->cbData == sizeof(HOSTEXECOUTCALLBACKDATA));
-        AssertPtr(pData);
-
-        if (   it->bCalled
-            && pData->cbData)
-        {
-            /* Do we need to resize the array? */
-            if (pData->cbData > cbData)
-                outputData.resize(pData->cbData);
-
-            /* Fill output in supplied out buffer. */
-            memcpy(outputData.raw(), pData->pvData, pData->cbData);
-            outputData.resize(pData->cbData); /* Shrink to fit actual buffer size. */
-        }
-        else
-            vrc = VERR_NO_DATA; /* This is not an error we want to report to COM. */
-
+                vrc = VERR_NO_DATA; /* This is not an error we want to report to COM. */
+
+            alock.release();
+        }
+
+        /* If something failed (or there simply was no data, indicated by VERR_NO_DATA,
+         * we return an empty array so that the frontend knows when to give up. */
         if (RT_FAILURE(vrc) || FAILED(rc))
             outputData.resize(0);
