VirtualBox

Ignore:
Timestamp:
Nov 25, 2011 10:11:06 AM (13 years ago)
Author:
vboxsync
Message:

GuestCtrl: Added support for explicitly waiting on stdout/stderr, bugfixes, logging adjustments.

Location:
trunk/src/VBox/Additions/common/VBoxService
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

    r39392 r39418  
    314314            /* Tell the host. */
    315315            rc = VbglR3GuestCtrlExecReportStatus(uClientID, uContextID, 0 /* PID, invalid. */,
    316                                                  PROC_STS_ERROR, VERR_MAX_PROCS_REACHED,
     316                                                 PROC_STS_ERROR,
     317                                                 !fAllowed ? VERR_MAX_PROCS_REACHED : rc,
    317318                                                 NULL /* pvData */, 0 /* cbData */);
    318319        }
     
    335336 * @param   pcbRead                 Pointer to number of bytes read.  Optional.
    336337 */
    337 int VBoxServiceControlExecGetOutput(uint32_t uPID, uint32_t uHandleId, uint32_t uTimeout,
     338int VBoxServiceControlExecGetOutput(uint32_t uPID, uint32_t uCID,
     339                                    uint32_t uHandleId, uint32_t uTimeout,
    338340                                    void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead)
    339341{
     
    345347
    346348    VBOXSERVICECTRLREQUEST ctrlRequest;
     349    ctrlRequest.uCID   = uCID;
    347350    ctrlRequest.cbData = cbBuf;
    348351    ctrlRequest.pvData = (uint8_t*)pvBuf;
     
    389392 * @param   pcbWritten              Pointer to number of bytes written to the process.  Optional.
    390393 */
    391 int VBoxServiceControlSetInput(uint32_t uPID, bool fPendingClose,
     394int VBoxServiceControlSetInput(uint32_t uPID, uint32_t uCID,
     395                               bool fPendingClose,
    392396                               void *pvBuf, uint32_t cbBuf,
    393397                               uint32_t *pcbWritten)
     
    400404
    401405    VBOXSERVICECTRLREQUEST ctrlRequest;
     406    ctrlRequest.uCID    = uCID;
    402407    ctrlRequest.cbData  = cbBuf;
    403408    ctrlRequest.pvData  = pvBuf;
     
    470475        }
    471476
    472         rc = VBoxServiceControlSetInput(uPID, fPendingClose, pabBuffer,
     477        rc = VBoxServiceControlSetInput(uPID, uContextID, fPendingClose, pabBuffer,
    473478                                        cbSize, &cbWritten);
    474         VBoxServiceVerbose(4, "Control: [PID %u]: Written input, rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n",
    475                            uPID, rc, uFlags, fPendingClose, cbSize, cbWritten);
     479        VBoxServiceVerbose(4, "Control: [PID %u]: Written input, CID=%u, rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n",
     480                           uPID, uContextID, rc, uFlags, fPendingClose, cbSize, cbWritten);
    476481        if (RT_SUCCESS(rc))
    477482        {
     
    543548        if (pBuf)
    544549        {
    545             rc = VBoxServiceControlExecGetOutput(uPID, uHandleID, RT_INDEFINITE_WAIT /* Timeout */,
     550            rc = VBoxServiceControlExecGetOutput(uPID, uContextID, uHandleID, RT_INDEFINITE_WAIT /* Timeout */,
    546551                                                 pBuf, _64K /* cbSize */, &cbRead);
     552
     553            /** Note: Don't convert/touch/modify/whatever the output data here! This might be binary
     554             *        data which the host needs to work with -- so just pass through all data unfiltered! */
     555
    547556            if (RT_SUCCESS(rc))
    548                 VBoxServiceVerbose(3, "Control: [PID %u]: Got output, CID=%u, cbRead=%u, uHandle=%u, uFlags=%u\n",
     557                VBoxServiceVerbose(2, "Control: Got output, PID=%u, CID=%u, cbRead=%u, uHandle=%u, uFlags=%u\n",
    549558                                   uPID, uContextID, cbRead, uHandleID, uFlags);
     559            else if (rc == VERR_NOT_FOUND)
     560                VBoxServiceVerbose(2, "Control: PID=%u not found, CID=%u, uHandle=%u\n",
     561                                   uPID, uContextID, uHandleID, rc);
    550562            else
    551                 VBoxServiceError("Control: [PID %u]: Failed to retrieve output, CID=%u, uHandle=%u, rc=%Rrc\n",
     563                VBoxServiceError("Control: Failed to retrieve output for PID=%u, CID=%u, uHandle=%u, rc=%Rrc\n",
    552564                                 uPID, uContextID, uHandleID, rc);
    553565            /* Note: Since the context ID is unique the request *has* to be completed here,
     
    598610
    599611
     612/**
     613 * Destroys all guest process threads which are still active.
     614 */
    600615static void VBoxServiceControlDestroyThreads(void)
    601616{
    602     VBoxServiceVerbose(3, "Control: Destroying threads ...\n");
     617    VBoxServiceVerbose(2, "Control: Destroying threads ...\n");
    603618
    604619    /* Signal all threads that we want to shutdown. */
     
    625640    }
    626641
     642#ifdef DEBUG
     643        PVBOXSERVICECTRLTHREAD pThreadCur;
     644        uint32_t cThreads = 0;
     645        RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node)
     646            cThreads++;
     647        VBoxServiceVerbose(4, "Control: Guest process threads left=%u\n", cThreads);
     648#endif
    627649    AssertMsg(RTListIsEmpty(&g_GuestControlThreads),
    628650              ("Guest process thread list still contains children when it should not\n"));
     
    680702            RTListForEach(&g_GuestControlThreads, pThread, VBOXSERVICECTRLTHREAD, Node)
    681703            {
    682     // THREAD LOCKING!!
    683                 Assert(pThread->fStarted != pThread->fStopped);
    684                 if (pThread->fStarted)
     704                VBOXSERVICECTRLTHREADSTATUS enmStatus = VBoxServiceControlThreadGetStatus(pThread);
     705                if (enmStatus == VBOXSERVICECTRLTHREADSTATUS_STARTED)
    685706                    uProcsRunning++;
    686                 else if (pThread->fStopped)
     707                else if (enmStatus == VBOXSERVICECTRLTHREADSTATUS_STOPPED)
    687708                    uProcsStopped++;
    688709                else
     
    690711            }
    691712
    692             VBoxServiceVerbose(2, "Control: Maximum served guest processes set to %u, running=%u, stopped=%u\n",
     713            VBoxServiceVerbose(3, "Control: Maximum served guest processes set to %u, running=%u, stopped=%u\n",
    693714                               g_GuestControlProcsMaxKept, uProcsRunning, uProcsStopped);
    694715
     
    714735
    715736/**
    716  * Finds a (formerly) started process given by its PID.
     737 * Finds a (formerly) started process given by its PID and locks it. Must be unlocked
     738 * by the caller with VBoxServiceControlThreadUnlock().
    717739 *
    718740 * @return  PVBOXSERVICECTRLTHREAD      Process structure if found, otherwise NULL.
    719741 * @param   uPID                        PID to search for.
    720742 */
    721 PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadByPID(uint32_t uPID)
     743const PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadLocked(uint32_t uPID)
    722744{
    723745    PVBOXSERVICECTRLTHREAD pThread = NULL;
     
    730752            if (pThreadCur->uPID == uPID)
    731753            {
    732                 pThread = pThreadCur;
     754                rc = RTCritSectEnter(&pThreadCur->CritSect);
     755                if (RT_SUCCESS(rc))
     756                    pThread = pThreadCur;
    733757                break;
    734758            }
     
    745769
    746770/**
     771 * Unlocks a previously locked guest process thread.
     772 *
     773 * @param   pThread                 Thread to unlock.
     774 */
     775void VBoxServiceControlThreadUnlock(const PVBOXSERVICECTRLTHREAD pThread)
     776{
     777    AssertPtr(pThread);
     778
     779    int rc = RTCritSectLeave(&pThread->CritSect);
     780    AssertRC(rc);
     781}
     782
     783
     784/**
     785 * Assigns a valid PID to a guest control thread and also checks if there already was
     786 * another (stale) guest process which was using that PID before and destroys it.
     787 *
     788 * @return  IPRT status code.
     789 * @param   pThread        Thread to assign PID to.
     790 * @param   uPID           PID to assign to the specified guest control execution thread.
     791 */
     792int VBoxServiceControlAssignPID(PVBOXSERVICECTRLTHREAD pThread, uint32_t uPID)
     793{
     794    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
     795    AssertReturn(uPID, VERR_INVALID_PARAMETER);
     796
     797    int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect);
     798    if (RT_SUCCESS(rc))
     799    {
     800        /* Search old threads using the desired PID and shut them down completely -- it's
     801         * not used anymore. */
     802        PVBOXSERVICECTRLTHREAD pThreadCur;
     803        RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node)
     804        {
     805            if (   pThreadCur->uPID == uPID
     806                && pThreadCur       != pThread)
     807            {
     808                VBoxServiceVerbose(2, "ControlThread: PID %u was used before, shutting down stale exec thread ...\n",
     809                                   uPID);
     810                rc = VBoxServiceControlThreadSignalShutdown(pThreadCur);
     811                if (RT_SUCCESS(rc))
     812                    rc = VBoxServiceControlThreadWaitForShutdown(pThreadCur,
     813                                                                 30 * 1000 /* Wait 30 seconds max. */);
     814            }
     815        }
     816
     817        /* Assign PID to current thread. */
     818        pThread->uPID = uPID;
     819
     820        rc = RTCritSectLeave(&g_GuestControlThreadsCritSect);
     821        AssertRC(rc);
     822    }
     823
     824    return rc;
     825}
     826
     827
     828/**
    747829 * Removes the specified guest process thread from the global thread
    748830 * list.
     
    751833 * @param   pThread             Thread to remove.
    752834 */
    753 void VBoxServiceControlRemoveThread(PVBOXSERVICECTRLTHREAD pThread)
     835void VBoxServiceControlRemoveThread(const PVBOXSERVICECTRLTHREAD pThread)
    754836{
    755837    if (!pThread)
     
    763845        RTListNodeRemove(&pThread->Node);
    764846
    765         int rc2 = RTCritSectLeave(&g_GuestControlThreadsCritSect);
    766         AssertRC(rc2);
     847#ifdef DEBUG
     848        PVBOXSERVICECTRLTHREAD pThreadCur;
     849        uint32_t cThreads = 0;
     850        RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node)
     851            cThreads++;
     852        VBoxServiceVerbose(4, "Control: Guest process threads left=%u\n", cThreads);
     853#endif
     854        rc = RTCritSectLeave(&g_GuestControlThreadsCritSect);
     855        AssertRC(rc);
    767856    }
    768857}
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp

    r39393 r39418  
    4242
    4343/* Internal functions. */
    44 static int vboxServiceControlThreadAssignPID(PVBOXSERVICECTRLTHREAD pData, uint32_t uPID);
    45 static void vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pData);
    46 static int vboxServiceControlThreadShutdown(PVBOXSERVICECTRLTHREAD pThread);
     44static int vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread);
    4745
    4846/**
     
    154152
    155153/**
     154 * Frees a guest thread.
     155 *
     156 * @return  IPRT status code.
     157 * @param   pThread                 Thread to shut down.
     158 */
     159static int vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread)
     160{
     161    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
     162
     163    VBoxServiceVerbose(1, "ControlThread: [PID %u]: Shutting down ...\n",
     164                       pThread->uPID);
     165
     166    /* Signal the request event to unblock potential waiters. */
     167    int rc = RTSemEventMultiSignal(pThread->RequestEvent);
     168    if (RT_FAILURE(rc))
     169        VBoxServiceError("ControlThread: [PID %u]: Signalling request event failed, rc=%Rrc\n",
     170                         pThread->uPID, rc);
     171
     172    rc = RTCritSectEnter(&pThread->CritSect);
     173    if (RT_SUCCESS(rc))
     174    {
     175        VBoxServiceVerbose(3, "ControlThread: [PID %u]: Freeing thread data ...\n",
     176                           pThread->uPID);
     177
     178        RTStrFree(pThread->pszCmd);
     179        if (pThread->uNumEnvVars)
     180        {
     181            for (uint32_t i = 0; i < pThread->uNumEnvVars; i++)
     182                RTStrFree(pThread->papszEnv[i]);
     183            RTMemFree(pThread->papszEnv);
     184        }
     185        RTGetOptArgvFree(pThread->papszArgs);
     186        RTStrFree(pThread->pszUser);
     187        RTStrFree(pThread->pszPassword);
     188
     189        rc = RTSemEventMultiDestroy(pThread->RequestEvent);
     190        AssertRC(rc);
     191
     192        VBoxServiceVerbose(3, "ControlThread: [PID %u]: Cleaning up ...\n",
     193                           pThread->uPID);
     194
     195        /* Set stopped status. */
     196        ASMAtomicXchgBool(&pThread->fStopped, true);
     197
     198        rc = RTCritSectLeave(&pThread->CritSect);
     199        AssertRC(rc);
     200    }
     201
     202    /*
     203     * Destroy other thread data.
     204     */
     205    if (RTCritSectIsInitialized(&pThread->CritSect))
     206        RTCritSectDelete(&pThread->CritSect);
     207
     208    /*
     209     * Destroy thread structure as final step.
     210     */
     211    RTMemFree(pThread);
     212    pThread = NULL;
     213
     214    return rc;
     215}
     216
     217
     218/**
    156219 * Signals a guest process thread that we want it to shut down in
    157220 * a gentle way.
     
    164227    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
    165228
    166     VBoxServiceVerbose(3, "ControlThead: [PID %u]: Signalling shutdown ...\n",
     229    VBoxServiceVerbose(3, "ControlThread: [PID %u]: Signalling shutdown ...\n",
    167230                       pThread->uPID);
    168231
     
    176239    int rc = VBoxServiceControlThreadPerform(pThread->uPID, &ctrlRequest);
    177240    if (RT_FAILURE(rc))
    178         VBoxServiceVerbose(3, "ControlThead: [PID %u]: Sending quit request failed with rc=%Rrc\n",
     241        VBoxServiceVerbose(3, "ControlThread: [PID %u]: Sending quit request failed with rc=%Rrc\n",
    179242                           pThread->uPID, rc);
    180243    return rc;
     
    197260        && !ASMAtomicReadBool(&pThread->fStopped)) /* Only shutdown threads which aren't yet. */
    198261    {
    199         VBoxServiceVerbose(3, "ControlThead: [PID %u]: Waiting for shutdown ...\n",
     262        VBoxServiceVerbose(2, "ControlThread: [PID %u]: Waiting for shutdown ...\n",
    200263                           pThread->uPID);
    201264
     
    205268        if (RT_FAILURE(rcThread))
    206269        {
    207             VBoxServiceError("ControlThead: [PID %u]: Shutdown returned error rc=%Rrc\n",
     270            VBoxServiceError("ControlThread: [PID %u]: Shutdown returned error rc=%Rrc\n",
    208271                             pThread->uPID, rcThread);
    209272            if (RT_SUCCESS(rc))
     
    216279
    217280/**
    218  * Frees an allocated thread data structure along with all its allocated parameters.
    219  *
    220  * @param   pThread             Pointer to thread data to free.
    221  */
    222 static void vboxServiceControlThreadFree(const PVBOXSERVICECTRLTHREAD pThread)
    223 {
    224     if (!pThread)
    225         return;
    226 
    227     VBoxServiceVerbose(3, "ControlThead: [PID %u]: Freeing thread data ...\n",
    228                        pThread->uPID);
    229 
    230     RTStrFree(pThread->pszCmd);
    231     if (pThread->uNumEnvVars)
    232     {
    233         for (uint32_t i = 0; i < pThread->uNumEnvVars; i++)
    234             RTStrFree(pThread->papszEnv[i]);
    235         RTMemFree(pThread->papszEnv);
    236     }
    237     RTGetOptArgvFree(pThread->papszArgs);
    238     RTStrFree(pThread->pszUser);
    239     RTStrFree(pThread->pszPassword);
    240 
    241     if (pThread->RequestEvent != NIL_RTSEMEVENTMULTI)
    242     {
    243         int rc2 = RTSemEventMultiDestroy(pThread->RequestEvent);
    244         AssertRC(rc2);
    245     }
     281 * Returns the guest process thread's current status.
     282 *
     283 * @return  VBOXSERVICECTRLTHREADSTATUS
     284 * @param   pThread             Thread to determine current status for.
     285 */
     286VBOXSERVICECTRLTHREADSTATUS VBoxServiceControlThreadGetStatus(const PVBOXSERVICECTRLTHREAD pThread)
     287{
     288    AssertPtrReturn(pThread, VBOXSERVICECTRLTHREADSTATUS_UNKNOWN);
     289
     290    int rc = RTCritSectEnter(&pThread->CritSect);
     291    if (RT_SUCCESS(rc))
     292    {
     293        Assert(pThread->fStarted != pThread->fStopped);
     294
     295        VBOXSERVICECTRLTHREADSTATUS enmStatus = VBOXSERVICECTRLTHREADSTATUS_UNKNOWN;
     296        /** @todo Add more logic here. */
     297        /** @todo Remove fStarted/fStopped and just use this VBOXSERVICECTRLTHREADSTATUS. */
     298        if (pThread->fStarted)
     299            enmStatus = VBOXSERVICECTRLTHREADSTATUS_STARTED;
     300        else if (pThread->fStopped)
     301            enmStatus = VBOXSERVICECTRLTHREADSTATUS_STOPPED;
     302        else
     303            AssertMsgFailed(("ControlThread: Uknown thread status (0x%x)\n"));
     304
     305        rc = RTCritSectLeave(&pThread->CritSect);
     306        AssertRC(rc);
     307
     308        return enmStatus;
     309    }
     310
     311    return VBOXSERVICECTRLTHREADSTATUS_UNKNOWN;
    246312}
    247313
     
    294360 *
    295361 */
     362static int VBoxServiceControlThreadHandleOutputError(RTPOLLSET hPollSet, uint32_t fPollEvt,
     363                                                     PRTPIPE phPipeR, uint32_t idPollHnd)
     364{
     365    int rc = VINF_SUCCESS;
     366
     367    rc = RTPollSetRemove(hPollSet, idPollHnd);
     368    AssertRC(rc);
     369
     370    rc = RTPipeClose(*phPipeR);
     371    AssertRC(rc);
     372    *phPipeR = NIL_RTPIPE;
     373
     374    return rc;
     375}
     376
     377
     378/**
     379 * Handle pending output data or error on standard out or standard error.
     380 *
     381 * @returns IPRT status code from client send.
     382 * @param   hPollSet            The polling set.
     383 * @param   fPollEvt            The event mask returned by RTPollNoResume.
     384 * @param   phPipeR             The pipe handle.
     385 * @param   idPollHnd           The pipe ID to handle.
     386 *
     387 */
    296388static int VBoxServiceControlThreadHandleOutputEvent(RTPOLLSET hPollSet, uint32_t fPollEvt,
    297389                                                     PRTPIPE phPipeR, uint32_t idPollHnd)
    298390{
    299391    int rc = VINF_SUCCESS;
    300 
    301 #if 0
    302     if (fPollEvt & RTPOLL_EVT_READ)
    303     {
    304         /** @todo Later: Notify the host about the read operation! */
    305 
    306         /* Make sure we go another poll round in case there was too much data
    307            for the buffer to hold. */
    308         fPollEvt &= RTPOLL_EVT_ERROR;
    309 
    310         /* Remove read event from poll set and just poll for errors from now on.
    311          * This is necessary for doing a RTPipeRead. */
    312         rc = RTPollSetEventsChange(hPollSet, idPollHnd, RTPOLL_EVT_ERROR);
    313         AssertRC(rc);
    314     }
     392    if (fPollEvt == RTPOLL_EVT_READ)
     393    {
     394        char abBuf[_64K];
     395        size_t cbRead;
     396        int rc = RTPipeRead(*phPipeR, abBuf, sizeof(abBuf), &cbRead);
     397        if (RT_SUCCESS(rc) && cbRead)
     398        {
     399#ifdef DEBUG
     400            VBoxServiceVerbose(4, "ControlThread: Drain idPollHnd=%u, abBuf=0x%p, cbRead=%u\n",
     401                               idPollHnd, abBuf, cbRead);
    315402#endif
    316 
     403            /* Goes to bit bucket ... */
     404
     405            /* Make sure we go another poll round in case there was too much data
     406               for the buffer to hold. */
     407            fPollEvt &= RTPOLL_EVT_ERROR;
     408        }
     409        else if (RT_FAILURE(rc))
     410        {
     411            fPollEvt |= RTPOLL_EVT_ERROR;
     412            AssertMsg(rc == VERR_BROKEN_PIPE, ("%Rrc\n", rc));
     413        }
     414    }
     415
     416    if (fPollEvt & RTPOLL_EVT_ERROR)
     417        rc = VBoxServiceControlThreadHandleOutputError(hPollSet, fPollEvt,
     418                                                       phPipeR, idPollHnd);
     419    return rc;
     420}
     421
     422
     423static int VBoxServiceControlThreadHandleRequest(RTPOLLSET hPollSet, uint32_t fPollEvt,
     424                                                 PRTPIPE phStdInW, PRTPIPE phStdOutR, PRTPIPE phStdErrR,
     425                                                 PVBOXSERVICECTRLTHREAD pThread)
     426{
    317427#ifdef DEBUG_andy
    318     VBoxServiceVerbose(4, "ControlThead: HandleOutputEvent fPollEvt=0x%x, idPollHnd=%u\n",
    319                        fPollEvt, idPollHnd);
    320 #endif
    321 
    322     /*
    323      * If an error was raised signalled
    324      */
    325     if (fPollEvt & RTPOLL_EVT_ERROR)
    326     {
    327         rc = RTPollSetRemove(hPollSet, idPollHnd);
    328         AssertRC(rc);
    329 
    330         rc = RTPipeClose(*phPipeR);
    331         AssertRC(rc);
    332         *phPipeR = NIL_RTPIPE;
    333     }
    334 
    335     return rc;
    336 }
    337 
    338 
    339 static int VBoxServiceControlThreadHandleIPCRequest(RTPOLLSET hPollSet, uint32_t fPollEvt,
    340                                                     PRTPIPE phStdInW, PRTPIPE phStdOutR, PRTPIPE phStdErrR,
    341                                                     PVBOXSERVICECTRLTHREAD pThread)
    342 {
    343 #ifdef DEBUG_andy
    344     VBoxServiceVerbose(4, "ControlThead: HandleIPCRequest\n");
     428    VBoxServiceVerbose(4, "ControlThread: HandleIPCRequest\n");
    345429#endif
    346430
     
    350434    AssertPtrReturn(phStdErrR, VERR_INVALID_POINTER);
    351435
    352     int rc = RTCritSectEnter(&pThread->CritSect);
     436    /*int rc = RTCritSectEnter(&pThread->CritSect);
    353437    if (RT_SUCCESS(rc))
    354     {
     438    {*/
    355439        /* Drain the notification pipe. */
    356440        uint8_t abBuf[8];
     
    358442        rc = RTPipeRead(pThread->hNotificationPipeR, abBuf, sizeof(abBuf), &cbIgnore);
    359443        if (RT_FAILURE(rc))
    360             VBoxServiceError("ControlThead: Draining IPC notification pipe failed with rc=%Rrc\n", rc);
     444            VBoxServiceError("ControlThread: Draining IPC notification pipe failed with rc=%Rrc\n", rc);
    361445
    362446        int rcReq = VINF_SUCCESS; /* Actual request result. */
     
    438522                     ? rcReq : rc;
    439523
    440         VBoxServiceVerbose(4, "ControlThead: Handled IPC request with rcReq=%Rrc, enmType=%u, cbData=%u\n",
    441                            rcReq, pRequest->enmType, pRequest->cbData);
     524        VBoxServiceVerbose(2, "ControlThread: [PID %u]: Handled req=%u, CID=%u, rcReq=%Rrc, cbData=%u\n",
     525                           pThread->uPID, pRequest->enmType, pRequest->uCID, rcReq, pRequest->cbData);
    442526
    443527        /* In any case, regardless of the result, we notify
     
    448532         * or modified already! */
    449533
    450         rc2 = RTCritSectLeave(&pThread->CritSect);
     534        /*rc2 = RTCritSectLeave(&pThread->CritSect);
    451535        AssertRC(rc2);
    452     }
     536    }*/
    453537
    454538    return rc;
     
    475559    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
    476560    AssertPtrReturn(phStdInW, VERR_INVALID_PARAMETER);
    477     AssertPtrReturn(phStdOutR, VERR_INVALID_PARAMETER);
    478     AssertPtrReturn(phStdErrR, VERR_INVALID_PARAMETER);
     561    /* Rest is optional. */
    479562
    480563    int                         rc;
     
    495578     * the first (stale) entry will be found and we get really weird results!
    496579     */
    497     rc = vboxServiceControlThreadAssignPID(pThread, hProcess);
     580    rc = VBoxServiceControlAssignPID(pThread, hProcess);
    498581    if (RT_FAILURE(rc))
    499582    {
    500         VBoxServiceError("ControlThead: Unable to assign PID to new thread, rc=%Rrc\n", rc);
     583        VBoxServiceError("ControlThread: Unable to assign PID=%u, to new thread, rc=%Rrc\n",
     584                         hProcess, rc);
    501585        return rc;
    502586    }
     
    506590     * and that it's now OK to send input to the process.
    507591     */
    508     VBoxServiceVerbose(3, "ControlThead: [PID %u]: Process started, CID=%u, User=%s\n",
    509                        pThread->uPID, pThread->uContextID, pThread->pszUser);
     592    VBoxServiceVerbose(2, "ControlThread: [PID %u]: Process \"%s\" started, CID=%u, User=%s\n",
     593                       pThread->uPID, pThread->pszCmd, pThread->uContextID, pThread->pszUser);
    510594    rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID,
    511595                                         pThread->uPID, PROC_STS_STARTED, 0 /* u32Flags */,
     
    531615        if (RT_SUCCESS(rc2))
    532616        {
    533             /*VBoxServiceVerbose(4, "ControlThead: [PID %u}: RTPollNoResume idPollHnd=%u\n",
     617            /*VBoxServiceVerbose(4, "ControlThread: [PID %u}: RTPollNoResume idPollHnd=%u\n",
    534618                                 pThread->uPID, idPollHnd);*/
    535619            switch (idPollHnd)
     
    550634
    551635                case VBOXSERVICECTRLPIPEID_IPC_NOTIFY:
    552                     rc = VBoxServiceControlThreadHandleIPCRequest(hPollSet, fPollEvt,
    553                                                                   phStdInW,phStdOutR,phStdErrR, pThread);
     636                    rc = VBoxServiceControlThreadHandleRequest(hPollSet, fPollEvt,
     637                                                               phStdInW, phStdOutR, phStdErrR, pThread);
    554638                    break;
    555639            }
     
    608692            if (cMsElapsed >= cMsTimeout)
    609693            {
    610                 VBoxServiceVerbose(3, "ControlThead: [PID %u]: Timed out (%ums elapsed > %ums timeout), killing ...",
     694                VBoxServiceVerbose(3, "ControlThread: [PID %u]: Timed out (%ums elapsed > %ums timeout), killing ...",
    611695                                   pThread->uPID, cMsElapsed, cMsTimeout);
    612696
     
    644728        if (MsProcessKilled == UINT64_MAX)
    645729        {
    646             VBoxServiceVerbose(3, "ControlThead: [PID %u]: Is still alive and not killed yet\n",
     730            VBoxServiceVerbose(3, "ControlThread: [PID %u]: Is still alive and not killed yet\n",
    647731                               pThread->uPID);
    648732
     
    654738        for (size_t i = 0; i < 10; i++)
    655739        {
    656             VBoxServiceVerbose(4, "ControlThead: [PID %u]: Kill attempt %d/10: Waiting to exit ...\n",
     740            VBoxServiceVerbose(4, "ControlThread: [PID %u]: Kill attempt %d/10: Waiting to exit ...\n",
    657741                               pThread->uPID, i + 1);
    658742            rc2 = RTProcWait(hProcess, RTPROCWAIT_FLAGS_NOBLOCK, &ProcessStatus);
    659743            if (RT_SUCCESS(rc2))
    660744            {
    661                 VBoxServiceVerbose(4, "ControlThead: [PID %u]: Kill attempt %d/10: Exited\n",
     745                VBoxServiceVerbose(4, "ControlThread: [PID %u]: Kill attempt %d/10: Exited\n",
    662746                                   pThread->uPID, i + 1);
    663747                fProcessAlive = false;
     
    666750            if (i >= 5)
    667751            {
    668                 VBoxServiceVerbose(4, "ControlThead: [PID %u]: Kill attempt %d/10: Trying to terminate ...\n",
     752                VBoxServiceVerbose(4, "ControlThread: [PID %u]: Kill attempt %d/10: Trying to terminate ...\n",
    669753                                   pThread->uPID, i + 1);
    670754                RTProcTerminate(hProcess);
     
    674758
    675759        if (fProcessAlive)
    676             VBoxServiceVerbose(3, "ControlThead: [PID %u]: Could not be killed\n", pThread->uPID);
     760            VBoxServiceVerbose(3, "ControlThread: [PID %u]: Could not be killed\n", pThread->uPID);
    677761    }
    678762
     
    688772        if (     fProcessTimedOut  && !fProcessAlive && MsProcessKilled != UINT64_MAX)
    689773        {
    690             VBoxServiceVerbose(3, "ControlThead: [PID %u]: Timed out and got killed\n",
     774            VBoxServiceVerbose(3, "ControlThread: [PID %u]: Timed out and got killed\n",
    691775                               pThread->uPID);
    692776            uStatus = PROC_STS_TOK;
     
    694778        else if (fProcessTimedOut  &&  fProcessAlive && MsProcessKilled != UINT64_MAX)
    695779        {
    696             VBoxServiceVerbose(3, "ControlThead: [PID %u]: Timed out and did *not* get killed\n",
     780            VBoxServiceVerbose(3, "ControlThread: [PID %u]: Timed out and did *not* get killed\n",
    697781                               pThread->uPID);
    698782            uStatus = PROC_STS_TOA;
     
    700784        else if (pThread->fShutdown && (fProcessAlive || MsProcessKilled != UINT64_MAX))
    701785        {
    702             VBoxServiceVerbose(3, "ControlThead: [PID %u]: Got terminated because system/service is about to shutdown\n",
     786            VBoxServiceVerbose(3, "ControlThread: [PID %u]: Got terminated because system/service is about to shutdown\n",
    703787                               pThread->uPID);
    704788            uStatus = PROC_STS_DWN; /* Service is stopping, process was killed. */
     
    707791        else if (fProcessAlive)
    708792        {
    709             VBoxServiceError("ControlThead: [PID %u]: Is alive when it should not!\n",
     793            VBoxServiceError("ControlThread: [PID %u]: Is alive when it should not!\n",
    710794                             pThread->uPID);
    711795        }
    712796        else if (MsProcessKilled != UINT64_MAX)
    713797        {
    714             VBoxServiceError("ControlThead: [PID %u]: Has been killed when it should not!\n",
     798            VBoxServiceError("ControlThread: [PID %u]: Has been killed when it should not!\n",
    715799                             pThread->uPID);
    716800        }
    717801        else if (ProcessStatus.enmReason == RTPROCEXITREASON_NORMAL)
    718802        {
    719             VBoxServiceVerbose(3, "ControlThead: [PID %u]: Ended with RTPROCEXITREASON_NORMAL (%u)\n",
     803            VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_NORMAL (%u)\n",
    720804                               pThread->uPID, ProcessStatus.iStatus);
    721805
     
    725809        else if (ProcessStatus.enmReason == RTPROCEXITREASON_SIGNAL)
    726810        {
    727             VBoxServiceVerbose(3, "ControlThead: [PID %u]: Ended with RTPROCEXITREASON_SIGNAL (%u)\n",
     811            VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_SIGNAL (%u)\n",
    728812                               pThread->uPID, ProcessStatus.iStatus);
    729813
     
    733817        else if (ProcessStatus.enmReason == RTPROCEXITREASON_ABEND)
    734818        {
    735             VBoxServiceVerbose(3, "ControlThead: [PID %u]: Ended with RTPROCEXITREASON_ABEND (%u)\n",
     819            VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_ABEND (%u)\n",
    736820                               pThread->uPID, ProcessStatus.iStatus);
    737821
     
    740824        }
    741825        else
    742             VBoxServiceVerbose(1, "ControlThead: [PID %u]: Handling process status %u not implemented\n",
     826            VBoxServiceVerbose(1, "ControlThread: [PID %u]: Handling process status %u not implemented\n",
    743827                               pThread->uPID, ProcessStatus.enmReason);
    744828
    745         VBoxServiceVerbose(3, "ControlThead: [PID %u]: Sending final status, ClientID=%u, CID=%u, Status=%u, Flags=0x%x\n",
     829        VBoxServiceVerbose(2, "ControlThread: [PID %u]: Ended, ClientID=%u, CID=%u, Status=%u, Flags=0x%x\n",
    746830                           pThread->uPID, pThread->uClientID, pThread->uContextID, uStatus, uFlags);
    747831        rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID,
     
    749833                                             NULL /* pvData */, 0 /* cbData */);
    750834        if (RT_FAILURE(rc))
    751             VBoxServiceError("ControlThead: [PID %u]: Error reporting final status to host; rc=%Rrc\n",
     835            VBoxServiceError("ControlThread: [PID %u]: Error reporting final status to host; rc=%Rrc\n",
    752836                             pThread->uPID, rc);
    753837
    754         VBoxServiceVerbose(3, "ControlThead: [PID %u]: Process loop ended with rc=%Rrc\n",
     838        VBoxServiceVerbose(3, "ControlThread: [PID %u]: Process loop ended with rc=%Rrc\n",
    755839                           pThread->uPID, rc);
    756840    }
    757841    else
    758         VBoxServiceError("ControlThead: [PID %u]: Loop failed with rc=%Rrc\n",
     842        VBoxServiceError("ControlThread: [PID %u]: Loop failed with rc=%Rrc\n",
    759843                         pThread->uPID, rc);
    760844    return rc;
     845}
     846
     847
     848static int vboxServiceControlThreadInitPipe(PRTHANDLE ph, PRTPIPE phPipe)
     849{
     850    AssertPtrReturn(ph, VERR_INVALID_PARAMETER);
     851    AssertPtrReturn(phPipe, VERR_INVALID_PARAMETER);
     852
     853    ph->enmType = RTHANDLETYPE_PIPE;
     854    ph->u.hPipe = NIL_RTPIPE;
     855    *phPipe     = NIL_RTPIPE;
     856
     857    return VINF_SUCCESS;
    761858}
    762859
     
    781878    AssertPtrReturn(phPipe, VERR_INVALID_PARAMETER);
    782879
    783     ph->enmType = RTHANDLETYPE_PIPE;
    784     ph->u.hPipe = NIL_RTPIPE;
    785     *pph        = NULL;
    786     *phPipe     = NIL_RTPIPE;
    787 
    788880    int rc;
    789881
     
    833925#endif
    834926#ifdef DEBUG
    835     VBoxServiceVerbose(3, "ControlThead: VBoxServiceControlExecMakeFullPath: %s -> %s\n",
     927    VBoxServiceVerbose(3, "ControlThread: VBoxServiceControlExecMakeFullPath: %s -> %s\n",
    836928                       pszPath, pszExpanded);
    837929#endif
     
    870962        rc = VBoxServiceControlThreadMakeFullPath(pszExecResolved, pszResolved, cbResolved);
    871963#ifdef DEBUG
    872         VBoxServiceVerbose(3, "ControlThead: VBoxServiceControlExecResolveExecutable: %s -> %s\n",
     964        VBoxServiceVerbose(3, "ControlThread: VBoxServiceControlExecResolveExecutable: %s -> %s\n",
    873965                           pszFileName, pszResolved);
    874966#endif
     
    10241116            if (fFlags)
    10251117            {
    1026                 /* Process Main flag "ExecuteProcessFlag_Hidden". */
    1027                 if (fFlags & RT_BIT(2))
     1118                if (fFlags & EXECUTEPROCESSFLAG_HIDDEN)
    10281119                    uProcFlags |= RTPROC_FLAGS_HIDDEN;
    1029                 /* Process Main flag "ExecuteProcessFlag_NoProfile". */
    1030                 if (fFlags & RT_BIT(3))
     1120                if (fFlags & EXECUTEPROCESSFLAG_NO_PROFILE)
    10311121                    uProcFlags |= RTPROC_FLAGS_NO_PROFILE;
    10321122            }
     
    10411131                uProcFlags |= RTPROC_FLAGS_SERVICE;
    10421132#ifdef DEBUG
    1043             VBoxServiceVerbose(3, "ControlThead: Command: %s\n", szExecExp);
     1133            VBoxServiceVerbose(3, "ControlThread: Command: %s\n", szExecExp);
    10441134            for (size_t i = 0; papszArgsExp[i]; i++)
    1045                 VBoxServiceVerbose(3, "ControlThead:\targv[%ld]: %s\n", i, papszArgsExp[i]);
     1135                VBoxServiceVerbose(3, "ControlThread:\targv[%ld]: %s\n", i, papszArgsExp[i]);
    10461136#endif
    10471137            /* Do normal execution. */
     
    10661156{
    10671157    AssertPtrReturn(pThread, VERR_INVALID_POINTER);
    1068     VBoxServiceVerbose(3, "ControlThead: Thread of process \"%s\" started\n", pThread->pszCmd);
     1158    VBoxServiceVerbose(3, "ControlThread: Thread of process \"%s\" started\n", pThread->pszCmd);
    10691159
    10701160    int rc = VbglR3GuestCtrlConnect(&pThread->uClientID);
    10711161    if (RT_FAILURE(rc))
    10721162    {
    1073         VBoxServiceError("ControlThead: Thread failed to connect to the guest control service, aborted! Error: %Rrc\n", rc);
     1163        VBoxServiceError("ControlThread: Thread failed to connect to the guest control service, aborted! Error: %Rrc\n", rc);
    10741164        RTThreadUserSignal(RTThreadSelf());
    10751165        return rc;
    10761166    }
    1077     VBoxServiceVerbose(3, "ControlThead: Guest process \"%s\" got client ID=%u\n",
    1078                        pThread->pszCmd, pThread->uClientID);
     1167    VBoxServiceVerbose(3, "ControlThread: Guest process \"%s\" got client ID=%u, flags=0x%x\n",
     1168                       pThread->pszCmd, pThread->uClientID, pThread->uFlags);
    10791169
    10801170    bool fSignalled = false; /* Indicator whether we signalled the thread user event already. */
     
    11301220                            /* Stdout. */
    11311221                            if (RT_SUCCESS(rc))
    1132                                 rc = RTPollSetAddPipe(hPollSet, hStdOutR, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDOUT);
     1222                            {
     1223                                uint32_t uFlags = RTPOLL_EVT_ERROR;
     1224                                if (!(pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDOUT))
     1225                                {
     1226                                    uFlags |= RTPOLL_EVT_READ;
     1227                                    VBoxServiceVerbose(3, "ControlThread: Host is not interested in getting stdout for \"%s\", poll flags=0x%x\n",
     1228                                                        pThread->pszCmd, uFlags);
     1229                                }
     1230                                rc = RTPollSetAddPipe(hPollSet, hStdOutR, uFlags, VBOXSERVICECTRLPIPEID_STDOUT);
     1231                            }
    11331232                            /* Stderr. */
    11341233                            if (RT_SUCCESS(rc))
    1135                                 rc = RTPollSetAddPipe(hPollSet, hStdErrR, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDERR);
     1234                            {
     1235                                uint32_t uFlags = RTPOLL_EVT_ERROR;
     1236                                if (!(pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDERR))
     1237                                {
     1238                                    uFlags |= RTPOLL_EVT_READ;
     1239                                    VBoxServiceVerbose(3, "ControlThread: Host is not interested in getting stderr for \"%s\", poll flags=0x%x\n",
     1240                                                        pThread->pszCmd, uFlags);
     1241                                }
     1242                                rc = RTPollSetAddPipe(hPollSet, hStdErrR, uFlags, VBOXSERVICECTRLPIPEID_STDERR);
     1243                            }
    11361244                            /* IPC notification pipe. */
    11371245                            if (RT_SUCCESS(rc))
     
    11481256                                                                           &hProcess);
    11491257                                if (RT_FAILURE(rc))
    1150                                     VBoxServiceError("ControlThead: Error starting process, rc=%Rrc\n", rc);
     1258                                    VBoxServiceError("ControlThread: Error starting process, rc=%Rrc\n", rc);
    11511259                                /*
    11521260                                 * Tell the control thread that it can continue
     
    11761284                                                                          hProcess, pThread->uTimeLimitMS, hPollSet,
    11771285                                                                          &pThread->pipeStdInW, &hStdOutR, &hStdErrR);
    1178 
    1179                                     /*
    1180                                      * Remove thread from global thread list. After this it's safe to shutdown
    1181                                      * and deallocate this thread.
    1182                                      */
    1183                                     VBoxServiceControlRemoveThread(pThread);
    1184 
    11851286                                    /*
    11861287                                     * The handles that are no longer in the set have
     
    12031304                                else /* Something went wrong; report error! */
    12041305                                {
    1205                                     VBoxServiceError("ControlThead: Could not start process '%s' (CID: %u)! Error: %Rrc\n",
     1306                                    VBoxServiceError("ControlThread: Could not start process '%s' (CID: %u)! Error: %Rrc\n",
    12061307                                                     pThread->pszCmd, pThread->uContextID, rc);
    12071308
     
    12101311                                                                          NULL /* pvData */, 0 /* cbData */);
    12111312                                    if (RT_FAILURE(rc2))
    1212                                         VBoxServiceError("ControlThead: Could not report process start error! Error: %Rrc (process error %Rrc)\n",
     1313                                        VBoxServiceError("ControlThread: Could not report process start error! Error: %Rrc (process error %Rrc)\n",
    12131314                                                         rc2, rc);
    12141315                                }
     
    12381339    if (pThread->uClientID)
    12391340    {
    1240         VBoxServiceVerbose(3, "ControlThead: [PID %u]: Cancelling pending waits (client ID=%u)\n",
     1341        VBoxServiceVerbose(3, "ControlThread: [PID %u]: Cancelling pending waits (client ID=%u)\n",
    12411342                           pThread->uPID, pThread->uClientID);
    12421343        int rc2 = VbglR3GuestCtrlCancelPendingWaits(pThread->uClientID);
    12431344        if (RT_FAILURE(rc2))
    12441345        {
    1245             VBoxServiceError("ControlThead: [PID %u]: Cancelling pending waits failed; rc=%Rrc\n",
     1346            VBoxServiceError("ControlThread: [PID %u]: Cancelling pending waits failed; rc=%Rrc\n",
    12461347                             pThread->uPID, rc2);
    12471348            if (RT_SUCCESS(rc))
     
    12501351
    12511352        /* Disconnect from guest control service. */
    1252         VBoxServiceError("ControlThead: [PID %u]: Disconnecting (client ID=%u) ...\n",
    1253                          pThread->uPID, pThread->uClientID);
     1353        VBoxServiceVerbose(3, "ControlThread: [PID %u]: Disconnecting (client ID=%u) ...\n",
     1354                           pThread->uPID, pThread->uClientID);
    12541355        VbglR3GuestCtrlDisconnect(pThread->uClientID);
    12551356        pThread->uClientID = 0;
    12561357    }
    12571358
    1258     VBoxServiceVerbose(3, "ControlThead: [PID %u]: Thread of process \"%s\" ended with rc=%Rrc\n",
     1359    VBoxServiceVerbose(3, "ControlThread: [PID %u]: Thread of process \"%s\" ended with rc=%Rrc\n",
    12591360                       pThread->uPID, pThread->pszCmd, rc);
    12601361
     
    12681369        RTThreadUserSignal(RTThreadSelf());
    12691370
    1270     int rc2 = vboxServiceControlThreadShutdown(pThread);
     1371    /*
     1372     * Remove thread from global thread list. After this it's safe to shutdown
     1373     * and deallocate this thread.
     1374     */
     1375    VBoxServiceControlRemoveThread(pThread);
     1376
     1377    int rc2 = vboxServiceControlThreadFree(pThread);
    12711378    if (RT_SUCCESS(rc))
    12721379        rc = rc2;
     
    13481455        if (RT_FAILURE(rc))
    13491456        {
    1350             VBoxServiceError("ControlThead: RTThreadCreate failed, rc=%Rrc\n, pThread=%p\n",
     1457            VBoxServiceError("ControlThread: RTThreadCreate failed, rc=%Rrc\n, pThread=%p\n",
    13511458                             rc, pThread);
    13521459        }
    13531460        else
    13541461        {
    1355             VBoxServiceVerbose(4, "ControlThead: Waiting for thread to initialize ...\n");
     1462            VBoxServiceVerbose(4, "ControlThread: Waiting for thread to initialize ...\n");
    13561463
    13571464            /* Wait for the thread to initialize. */
     
    13591466            if (ASMAtomicReadBool(&pThread->fShutdown))
    13601467            {
    1361                 VBoxServiceError("ControlThead: Thread for process \"%s\" failed to start!\n", pszCmd);
     1468                VBoxServiceError("ControlThread: Thread for process \"%s\" failed to start!\n", pszCmd);
    13621469                rc = VERR_GENERAL_FAILURE;
    13631470            }
     
    13801487
    13811488/**
    1382  * Assigns a valid PID to a guest control thread and also checks if there already was
    1383  * another (stale) guest process which was using that PID before and destroys it.
    1384  *
    1385  * @return  IPRT status code.
    1386  * @param   pData          Pointer to guest control execution thread data.
    1387  * @param   uPID           PID to assign to the specified guest control execution thread.
    1388  */
    1389 int vboxServiceControlThreadAssignPID(PVBOXSERVICECTRLTHREAD pThread, uint32_t uPID)
    1390 {
    1391     AssertPtrReturn(pThread, VERR_INVALID_POINTER);
    1392     AssertReturn(uPID, VERR_INVALID_PARAMETER);
    1393 
    1394     int rc = VINF_SUCCESS;
    1395 
    1396     /* Search an old thread using the desired PID and shut it down completely -- it's
    1397      * not used anymore. */
    1398     PVBOXSERVICECTRLTHREAD pOldThread = VBoxServiceControlGetThreadByPID(uPID);
    1399     if (   pOldThread
    1400         && pOldThread != pThread)
    1401     {
    1402         PVBOXSERVICECTRLTHREAD pNext = RTListNodeGetNext(&pOldThread->Node, VBOXSERVICECTRLTHREAD, Node);
    1403 
    1404         VBoxServiceVerbose(3, "ControlThead: PID %u was used before, shutting down stale exec thread ...\n",
    1405                            uPID);
    1406         rc = vboxServiceControlThreadShutdown(pOldThread);
    1407         if (RT_FAILURE(rc))
    1408         {
    1409             VBoxServiceVerbose(3, "ControlThead: Unable to shut down stale exec thread, rc=%Rrc\n", rc);
    1410             /* Keep going. */
    1411         }
    1412     }
    1413 
    1414     /* Assign PID to current thread. */
    1415     pThread->uPID = uPID;
    1416 
    1417     return rc;
    1418 }
    1419 
    1420 
    1421 /**
    14221489 * Performs a request to a specific (formerly started) guest process and waits
    14231490 * for its response.
     
    14331500    /* Rest in pRequest is optional (based on the request type). */
    14341501
    1435     VBoxServiceVerbose(4, "ControlThead: Performing PID=%u, enmType=%u, pvData=0x%p, cbData=%u ...\n",
    1436                        uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData);
    1437 
    1438     int rc;
    1439     const PVBOXSERVICECTRLTHREAD pThread = VBoxServiceControlGetThreadByPID(uPID);
    1440     if (   pThread
    1441         && !ASMAtomicReadBool(&pThread->fStopped))
    1442     {
    1443         rc = RTCritSectEnter(&pThread->CritSect);
     1502    int rc = VINF_SUCCESS;
     1503    const PVBOXSERVICECTRLTHREAD pThread = VBoxServiceControlGetThreadLocked(uPID);
     1504    if (pThread)
     1505    {
     1506        /* Set request result to some defined state in case
     1507         * it got cancelled. */
     1508        pRequest->rc = VERR_CANCELLED;
     1509
     1510        /* Set request structure pointer. */
     1511        pThread->pRequest = pRequest;
     1512
     1513        /** @todo To speed up simultaneous guest process handling we could add a worker threads
     1514         *        or queue in order to wait for the request to happen. Later. */
     1515
     1516        /* Wake up guest thrad by sending a wakeup byte to the notification pipe so
     1517         * that RTPoll unblocks (returns) and we then can do our requested operation. */
     1518        if (pThread->hNotificationPipeW == NIL_RTPIPE)
     1519            rc = VERR_BROKEN_PIPE;
     1520        size_t cbWritten;
    14441521        if (RT_SUCCESS(rc))
    1445         {
    1446             /* Set request structure pointer. */
    1447             pThread->pRequest = pRequest;
    1448 
    1449             /** @todo To speed up simultaneous guest process handling we could add a worker threads
    1450              *        or queue in order to wait for the request to happen. Later. */
    1451 
    1452             /* Wake up guest thrad by sending a wakeup byte to the notification pipe so
    1453              * that RTPoll unblocks (returns) and we then can do our requested operation. */
    1454             if (pThread->hNotificationPipeW == NIL_RTPIPE)
    1455                 rc = VERR_BROKEN_PIPE;
    1456             size_t cbWritten;
     1522            rc = RTPipeWrite(pThread->hNotificationPipeW, "i", 1, &cbWritten);
     1523
     1524        if (   RT_SUCCESS(rc)
     1525            && cbWritten)
     1526        {
     1527            VBoxServiceVerbose(3, "ControlThread: [PID %u]: Waiting for response on enmType=%u, pvData=0x%p, cbData=%u\n",
     1528                               uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData);
     1529            /* Wait on the request to get completed (or we are asked to abort/shutdown). */
     1530            rc = RTSemEventMultiWait(pThread->RequestEvent, RT_INDEFINITE_WAIT);
    14571531            if (RT_SUCCESS(rc))
    1458                 rc = RTPipeWrite(pThread->hNotificationPipeW, "i", 1, &cbWritten);
    1459 
    1460             /* Make sure we leave the critical section before doing the wait. */
    1461             int rc2 = RTCritSectLeave(&pThread->CritSect);
    1462             AssertRCReturn(rc2, rc2);
    1463 
    1464             if (RT_SUCCESS(rc) && cbWritten)
    14651532            {
    1466                 VBoxServiceVerbose(4, "ControlThead: [PID %u]: Waiting for response on enmType=%u, pvData=0x%p, cbData=%u\n",
    1467                                    uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData);
    1468                 /* Wait on the request to get completed (or we are asked to abort/shutdown). */
    1469                 rc = RTSemEventMultiWait(pThread->RequestEvent, RT_INDEFINITE_WAIT);
    1470                 if (RT_SUCCESS(rc))
    1471                 {
    1472                     VBoxServiceVerbose(4, "ControlThead: [PID %u]: Performed with rc=%Rrc, cbData=%u\n",
    1473                                        uPID, pRequest->rc, pRequest->cbData);
    1474 
    1475                     rc = RTCritSectEnter(&pThread->CritSect);
    1476                     if (RT_SUCCESS(rc))
    1477                     {
    1478                         /* Give back overall request result. */
    1479                         rc = pRequest->rc;
    1480 
    1481                         /* Reset the semaphore. */
    1482                         rc2 = RTSemEventMultiReset(pThread->RequestEvent);
    1483                         if (RT_FAILURE(rc2))
    1484                             VBoxServiceError("ControlThead: Unable to reset request event, rc=%Rrc\n", rc2);
    1485 
    1486                         rc2 = RTCritSectLeave(&pThread->CritSect);
    1487                         AssertRCReturn(rc2, rc2);
    1488                     }
    1489                 }
     1533                VBoxServiceVerbose(4, "ControlThread: [PID %u]: Performed with rc=%Rrc, cbData=%u\n",
     1534                                   uPID, pRequest->rc, pRequest->cbData);
     1535
     1536                /* Give back overall request result. */
     1537                rc = pRequest->rc;
     1538
     1539                /* Reset the semaphore. */
     1540                int rc2 = RTSemEventMultiReset(pThread->RequestEvent);
     1541                if (RT_FAILURE(rc2))
     1542                    VBoxServiceError("ControlThread: [PID %u]: Unable to reset request event, rc=%Rrc\n",
     1543                                     uPID, rc2);
    14901544            }
    1491         }
     1545            else
     1546                VBoxServiceError("ControlThread: [PID %u]: Wait failed, rc=%Rrc\n",
     1547                                 uPID, rc);
     1548        }
     1549
     1550        VBoxServiceControlThreadUnlock(pThread);
    14921551    }
    14931552    else /* PID not found! */
    14941553        rc = VERR_NOT_FOUND;
    14951554
    1496     VBoxServiceVerbose(4, "ControlThead: Performed PID=%u, enmType=%u, pvData=0x%p, cbData=%u with rc=%Rrc\n",
    1497                        uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData, rc);
    1498     return rc;
    1499 }
    1500 
    1501 
    1502 /**
    1503  * Shuts down a guest thread.
    1504  *
    1505  * @return  IPRT status code.
    1506  * @param   pThread                 Thread to shut down.
    1507  */
    1508 static int vboxServiceControlThreadShutdown(PVBOXSERVICECTRLTHREAD pThread)
    1509 {
    1510     AssertPtrReturn(pThread, VERR_INVALID_POINTER);
    1511 
    1512     int rc = RTCritSectEnter(&pThread->CritSect);
    1513     if (RT_SUCCESS(rc))
    1514     {
    1515         VBoxServiceVerbose(3, "ControlThead: [PID %u]: Shutting down ...\n",
    1516                            pThread->uPID);
    1517 
    1518         /*
    1519          * Destroy thread-specific data.
    1520          */
    1521         vboxServiceControlThreadFree(pThread);
    1522 
    1523         /* Set stopped status. */
    1524         ASMAtomicXchgBool(&pThread->fStopped, true);
    1525 
    1526         rc = RTCritSectLeave(&pThread->CritSect);
    1527     }
    1528 
    1529     /*
    1530      * Destroy other thread data.
    1531      */
    1532     if (RTCritSectIsInitialized(&pThread->CritSect))
    1533         RTCritSectDelete(&pThread->CritSect);
    1534 
    1535     /*
    1536      * Destroy thread structure as final step.
    1537      */
    1538     RTMemFree(pThread);
    1539     pThread = NULL;
    1540 
    1541     return rc;
    1542 }
    1543 
     1555    VBoxServiceVerbose(3, "ControlThread: [PID %u]: Performed enmType=%u, uCID=%u, pvData=0x%p, cbData=%u, rc=%Rrc\n",
     1556                       uPID, pRequest->enmType, pRequest->uCID, pRequest->pvData, pRequest->cbData, rc);
     1557    return rc;
     1558}
     1559
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r39392 r39418  
    171171    /** Payload data; a pre-allocated data buffer for input/output. */
    172172    void                      *pvData;
     173    /** The context ID which is required to complete the
     174     *  request. */
     175    uint32_t                   uCID;
    173176    /** The overall result of the operation. */
    174177    int                        rc;
     
    230233/** Pointer to thread data. */
    231234typedef VBOXSERVICECTRLTHREAD *PVBOXSERVICECTRLTHREAD;
     235
     236/**
     237 * Request types to perform on a started guest process.
     238 */
     239typedef enum VBOXSERVICECTRLTHREADSTATUS
     240{
     241    /** Unknown status. Do not use / should not happen. */
     242    VBOXSERVICECTRLTHREADSTATUS_UNKNOWN          = 0,
     243    VBOXSERVICECTRLTHREADSTATUS_STARTED          = 100,
     244    VBOXSERVICECTRLTHREADSTATUS_STOPPED          = 200
     245} VBOXSERVICECTRLTHREADSTATUS;
    232246#endif /* VBOX_WITH_GUEST_CONTROL */
    233247#ifdef VBOX_WITH_GUEST_PROPS
     
    329343extern int          VBoxServiceControlHandleCmdSetInput(uint32_t u32ClientId, uint32_t uNumParms, size_t cbMaxBufSize);
    330344extern int          VBoxServiceControlHandleCmdGetOutput(uint32_t u32ClientId, uint32_t uNumParms);
    331 extern PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadByPID(uint32_t uPID);
    332 extern void         VBoxServiceControlRemoveThread(PVBOXSERVICECTRLTHREAD pThread);
     345extern const PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadLocked(uint32_t uPID);
     346extern void         VBoxServiceControlThreadUnlock(const PVBOXSERVICECTRLTHREAD pThread);
     347extern int          VBoxServiceControlAssignPID(PVBOXSERVICECTRLTHREAD pThread, uint32_t uPID);
     348extern void         VBoxServiceControlRemoveThread(const PVBOXSERVICECTRLTHREAD pThread);
    333349/* Guest process functions. */
     350extern VBOXSERVICECTRLTHREADSTATUS VBoxServiceControlThreadGetStatus(const PVBOXSERVICECTRLTHREAD pThread);
    334351extern int          VBoxServiceControlThreadStart(uint32_t uClientID, uint32_t uContext,
    335352                                                  const char *pszCmd, uint32_t uFlags,
     
    338355                                                  const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS,
    339356                                                  PRTLISTNODE *ppNode);
    340 int                 VBoxServiceControlThreadPerform(uint32_t uPID, PVBOXSERVICECTRLREQUEST pRequest);
     357extern int          VBoxServiceControlThreadPerform(uint32_t uPID, PVBOXSERVICECTRLREQUEST pRequest);
    341358extern int          VBoxServiceControlThreadSignalShutdown(const PVBOXSERVICECTRLTHREAD pThread);
    342359extern int          VBoxServiceControlThreadWaitForShutdown(const PVBOXSERVICECTRLTHREAD pThread, RTMSINTERVAL msTimeout);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette