VirtualBox

Changeset 38113 in vbox


Ignore:
Timestamp:
Jul 22, 2011 1:57:35 PM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
73065
Message:

VBoxService/GuestCtrl: Fixed stability issues due to PID recycling, enhanced and unified debug logging along with thread names to stdout.

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

Legend:

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

    r36745 r38113  
    5959/** The current verbosity level. */
    6060int g_cVerbosity = 0;
     61/** Critical section for (debug) logging. */
     62#ifdef DEBUG
     63 RTCRITSECT g_csLog;
     64#endif
    6165/** The default service interval (the -i | --interval) option). */
    6266uint32_t g_DefaultInterval = 0;
     
    217221void VBoxServiceVerbose(int iLevel, const char *pszFormat, ...)
    218222{
    219     if (iLevel <= g_cVerbosity)
    220     {
    221         RTStrmPrintf(g_pStdOut, "%s: ", g_pszProgName);
    222         va_list va;
    223         va_start(va, pszFormat);
    224         RTStrmPrintfV(g_pStdOut, pszFormat, va);
    225         va_end(va);
    226         va_start(va, pszFormat);
    227         LogRel(("%s: %N", g_pszProgName, pszFormat, &va));
    228         va_end(va);
    229     }
     223#ifdef DEBUG
     224    int rc = RTCritSectEnter(&g_csLog);
     225    if (RT_SUCCESS(rc))
     226    {
     227#endif
     228        if (iLevel <= g_cVerbosity)
     229        {
     230#ifdef DEBUG
     231            const char *pszThreadName = RTThreadSelfName();
     232            AssertPtr(pszThreadName);
     233            RTStrmPrintf(g_pStdOut, "%s [%s]: ",
     234                         g_pszProgName, pszThreadName);
     235#else
     236            RTStrmPrintf(g_pStdOut, "%s: ", g_pszProgName);
     237#endif
     238            va_list va;
     239            va_start(va, pszFormat);
     240            RTStrmPrintfV(g_pStdOut, pszFormat, va);
     241            va_end(va);
     242            va_start(va, pszFormat);
     243            LogRel(("%s: %N", g_pszProgName, pszFormat, &va));
     244            va_end(va);
     245        }
     246#ifdef DEBUG
     247        int rc2 = RTCritSectLeave(&g_csLog);
     248        if (RT_SUCCESS(rc))
     249            rc = rc2;
     250    }
     251#endif
    230252}
    231253
     
    580602        return RTMsgInitFailure(rc);
    581603    g_pszProgName = RTPathFilename(argv[0]);
     604#ifdef DEBUG
     605    rc = RTCritSectInit(&g_csLog);
     606    AssertRC(rc);
     607#endif
    582608
    583609#ifdef VBOXSERVICE_TOOLBOX
     
    851877
    852878    VBoxServiceVerbose(0, "Ended.\n");
     879
     880#ifdef DEBUG
     881    RTCritSectDelete(&g_csLog);
     882#endif
    853883    return rcExit;
    854884}
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp

    r38085 r38113  
    191191
    192192/**
    193  * Handle pending output data/error on standard out or standard error.
     193 * Handle pending output data/error on stdout or stderr.
    194194 *
    195195 * @return  IPRT status code.
     
    206206    AssertPtrReturn(pBuf, VERR_INVALID_POINTER);
    207207
    208 #ifdef DEBUG
    209     VBoxServiceVerbose(4, "ControlExec: HandleOutputEvent: fPollEvt=%#x, uHandle=%u\n",
    210                        fPollEvt, uHandleId);
    211 #endif
    212 
    213208    /*
    214209     * Try drain the pipe before acting on any errors.
     
    224219        rc = VBoxServicePipeBufWriteToBuf(pBuf, abBuf,
    225220                                          cbRead, false /* Pending close */, &cbWritten);
     221#ifdef DEBUG_andy
     222        VBoxServiceVerbose(4, "ControlExec: Written output event [%u %u], cbRead=%u, cbWritten=%u, rc=%Rrc, uHandleId=%u, fPollEvt=%#x\n",
     223                           pBuf->uPID, pBuf->uPipeId, cbRead, cbWritten, rc, uHandleId, fPollEvt);
     224#endif
    226225        if (RT_SUCCESS(rc))
    227226        {
     
    257256                                                   PRTPIPE phNotificationPipeR, PRTPIPE phInputPipeW)
    258257{
    259 #ifdef DEBUG
     258#ifdef DEBUG_andy
    260259    VBoxServiceVerbose(4, "ControlExec: HandleStdInputNotify\n");
    261260#endif
     
    317316    AssertPtr(pData);
    318317
    319     /* Assign PID to thread data. */
    320     pData->uPID = hProcess;
     318    /*
     319     * Assign PID to thread data.
     320     * Also check if there already was a thread with the same PID and shut it down -- otherwise
     321     * the first (stale) entry will be found and we get really weird results!
     322     */
     323    rc = VBoxServiceControlExecThreadAssignPID(pData, hProcess);
     324    if (RT_FAILURE(rc))
     325    {
     326        VBoxServiceError("ControlExec: Unable to assign PID to new thread, rc=%Rrc\n", rc);
     327        return rc;
     328    }
    321329
    322330    /*
     
    324332     * and that it's now OK to send input to the process.
    325333     */
    326     VBoxServiceVerbose(3, "ControlExec: Process started: PID=%u, CID=%u, User=%s\n",
     334    VBoxServiceVerbose(3, "ControlExec: [PID %u]: Process started, CID=%u, User=%s\n",
    327335                       pData->uPID, pThread->uContextID, pData->pszUser);
    328336    rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID,
     
    349357        if (RT_SUCCESS(rc2))
    350358        {
    351             VBoxServiceVerbose(4, "ControlExec: RTPollNoResume idPollHnd=%u\n", idPollHnd);
     359            /*VBoxServiceVerbose(4, "ControlExec: [PID %u}: RTPollNoResume idPollHnd=%u\n",
     360                                 pData->uPID, idPollHnd);*/
    352361            switch (idPollHnd)
    353362            {
     
    370379
    371380                case VBOXSERVICECTRLPIPEID_STDOUT:
     381#ifdef DEBUG
     382                    VBoxServiceVerbose(4, "ControlExec: [PID %u]: StdOut fPollEvt=%#x\n",
     383                                       pData->uPID, fPollEvt);
     384#endif
    372385                    rc = VBoxServiceControlExecProcHandleOutputEvent(hPollSet, fPollEvt, phStdOutR,
    373386                                                                     VBOXSERVICECTRLPIPEID_STDOUT, &pData->stdOut);
     387// TEST!!!
     388VBoxServicePipeBufIsEnabled(&pData->stdOut);
    374389                    break;
    375390
    376391                case VBOXSERVICECTRLPIPEID_STDERR:
     392#ifdef DEBUG
     393                    VBoxServiceVerbose(4, "ControlExec: [PID %u]: StdErr: fPollEvt=%#x\n",
     394                                       pData->uPID, fPollEvt);
     395#endif
    377396                    rc = VBoxServiceControlExecProcHandleOutputEvent(hPollSet, fPollEvt, phStdErrR,
    378397                                                                     VBOXSERVICECTRLPIPEID_STDERR, &pData->stdErr);
     
    380399
    381400                default:
    382                     AssertMsgFailed(("idPollHnd=%u fPollEvt=%#x\n", idPollHnd, fPollEvt));
     401                    AssertMsgFailed(("PID=%u idPollHnd=%u fPollEvt=%#x\n",
     402                                     pData->uPID, idPollHnd, fPollEvt));
    383403                    break;
    384404            }
     
    428448            if (cMsElapsed >= cMsTimeout)
    429449            {
    430                 VBoxServiceVerbose(3, "ControlExec: Process timed out (%ums elapsed > %ums timeout), killing ...", cMsElapsed, cMsTimeout);
     450                VBoxServiceVerbose(3, "ControlExec: [PID %u]: Timed out (%ums elapsed > %ums timeout), killing ...",
     451                                   pData->uPID, cMsElapsed, cMsTimeout);
    431452
    432453                fProcessTimedOut = true;
     
    463484        if (MsProcessKilled == UINT64_MAX)
    464485        {
    465             VBoxServiceVerbose(3, "ControlExec: Process (PID=%u) is still alive and not killed yet\n",
     486            VBoxServiceVerbose(3, "ControlExec: [PID %u]: Is still alive and not killed yet\n",
    466487                               pData->uPID);
    467488
     
    473494        for (size_t i = 0; i < 10; i++)
    474495        {
    475             VBoxServiceVerbose(4, "ControlExec: Kill attempt %d/10: Waiting for process (PID=%u) exit ...\n",
    476                                i + 1, pData->uPID);
     496            VBoxServiceVerbose(4, "ControlExec: [PID %u]: Kill attempt %d/10: Waiting to exit ...\n",
     497                               pData->uPID, i + 1);
    477498            rc2 = RTProcWait(hProcess, RTPROCWAIT_FLAGS_NOBLOCK, &ProcessStatus);
    478499            if (RT_SUCCESS(rc2))
    479500            {
    480                 VBoxServiceVerbose(4, "ControlExec: Kill attempt %d/10: Process (PID=%u) exited\n",
    481                                    i + 1, pData->uPID);
     501                VBoxServiceVerbose(4, "ControlExec: [PID %u]: Kill attempt %d/10: Exited\n",
     502                                   pData->uPID, i + 1);
    482503                fProcessAlive = false;
    483504                break;
     
    485506            if (i >= 5)
    486507            {
    487                 VBoxServiceVerbose(4, "ControlExec: Kill attempt %d/10: Try to terminate (PID=%u) ...\n",
    488                                    i + 1, pData->uPID);
     508                VBoxServiceVerbose(4, "ControlExec: [PID %u]: Kill attempt %d/10: Trying to terminate ...\n",
     509                                   pData->uPID, i + 1);
    489510                RTProcTerminate(hProcess);
    490511            }
     
    493514
    494515        if (fProcessAlive)
    495             VBoxServiceVerbose(3, "ControlExec: Process (PID=%u) could not be killed\n", pData->uPID);
     516            VBoxServiceVerbose(3, "ControlExec: [PID %u]: Could not be killed\n", pData->uPID);
    496517    }
    497518
    498519    /*
    499      * If we don't have a client problem (RT_FAILURE(rc) we'll reply to the
     520     * If we don't have a client problem (RT_FAILURE(rc)) we'll reply to the
    500521     * clients exec packet now.
    501522     */
     
    516537        if (     fProcessTimedOut  && !fProcessAlive && MsProcessKilled != UINT64_MAX)
    517538        {
    518             VBoxServiceVerbose(3, "ControlExec: Process timed out and got killed\n");
     539            VBoxServiceVerbose(3, "ControlExec: [PID %u]: Timed out and got killed\n",
     540                               pData->uPID);
    519541            uStatus = PROC_STS_TOK;
    520542        }
    521543        else if (fProcessTimedOut  &&  fProcessAlive && MsProcessKilled != UINT64_MAX)
    522544        {
    523             VBoxServiceVerbose(3, "ControlExec: Process timed out and did *not* get killed\n");
     545            VBoxServiceVerbose(3, "ControlExec: [PID %u]: Timed out and did *not* get killed\n",
     546                               pData->uPID);
    524547            uStatus = PROC_STS_TOA;
    525548        }
    526549        else if (pThread->fShutdown && (fProcessAlive || MsProcessKilled != UINT64_MAX))
    527550        {
    528             VBoxServiceVerbose(3, "ControlExec: Process got terminated because system/service is about to shutdown\n");
     551            VBoxServiceVerbose(3, "ControlExec: [PID %u]: Got terminated because system/service is about to shutdown\n",
     552                               pData->uPID);
    529553            uStatus = PROC_STS_DWN; /* Service is stopping, process was killed. */
    530554            uFlags = pData->uFlags; /* Return handed-in execution flags back to the host. */
     
    532556        else if (fProcessAlive)
    533557        {
    534             VBoxServiceError("ControlExec: Process is alive when it should not!\n");
     558            VBoxServiceError("ControlExec: [PID %u]: Is alive when it should not!\n",
     559                             pData->uPID);
    535560        }
    536561        else if (MsProcessKilled != UINT64_MAX)
    537562        {
    538             VBoxServiceError("ControlExec: Process has been killed when it should not!\n");
     563            VBoxServiceError("ControlExec: [PID %u]: Has been killed when it should not!\n",
     564                             pData->uPID);
    539565        }
    540566        else if (ProcessStatus.enmReason == RTPROCEXITREASON_NORMAL)
    541567        {
    542             VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_NORMAL (%u)\n",
    543                                ProcessStatus.iStatus);
     568            VBoxServiceVerbose(3, "ControlExec: [PID %u]: Ended with RTPROCEXITREASON_NORMAL (%u)\n",
     569                               pData->uPID, ProcessStatus.iStatus);
    544570
    545571            uStatus = PROC_STS_TEN;
     
    548574        else if (ProcessStatus.enmReason == RTPROCEXITREASON_SIGNAL)
    549575        {
    550             VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_SIGNAL (%u)\n",
    551                                ProcessStatus.iStatus);
     576            VBoxServiceVerbose(3, "ControlExec: [PID %u]: Ended with RTPROCEXITREASON_SIGNAL (%u)\n",
     577                               pData->uPID, ProcessStatus.iStatus);
    552578
    553579            uStatus = PROC_STS_TES;
     
    556582        else if (ProcessStatus.enmReason == RTPROCEXITREASON_ABEND)
    557583        {
    558             VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_ABEND (%u)\n",
    559                                ProcessStatus.iStatus);
     584            VBoxServiceVerbose(3, "ControlExec: [PID %u]: Ended with RTPROCEXITREASON_ABEND (%u)\n",
     585                               pData->uPID, ProcessStatus.iStatus);
    560586
    561587            uStatus = PROC_STS_TEA;
     
    563589        }
    564590        else
    565         {
    566             VBoxServiceError("ControlExec: Process has reached an undefined status!\n");
    567         }
    568 
    569         VBoxServiceVerbose(3, "ControlExec: Process ended: PID=%u, CID=%u, Status=%u, Flags=%u\n",
     591            VBoxServiceError("ControlExec: [PID %u]: Reached an undefined state!\n",
     592                             pData->uPID);
     593
     594        VBoxServiceVerbose(3, "ControlExec: [PID %u]: Ended, CID=%u, Status=%u, Flags=%u\n",
    570595                           pData->uPID, pThread->uContextID, uStatus, uFlags);
    571596        rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID,
    572597                                             pData->uPID, uStatus, uFlags,
    573598                                             NULL /* pvData */, 0 /* cbData */);
    574         VBoxServiceVerbose(3, "ControlExec: Process loop ended with rc=%Rrc\n", rc);
     599        VBoxServiceVerbose(3, "ControlExec: [PID %u]: Process loop ended with rc=%Rrc\n",
     600                           pData->uPID, rc);
    575601
    576602        /*
     
    580606        if (g_cVerbosity >= 5)
    581607        {
    582             VBoxServiceVerbose(5, "StdOut of process (PID %u):\n", pData->uPID);
     608            VBoxServiceVerbose(5, "[PID %u]: StdOut:\n", pData->uPID);
    583609
    584610            uint8_t szBuf[_64K];
     
    589615                   && cbRead)
    590616            {
    591                 RTStrmWrite(g_pStdOut, szBuf, cbRead);
    592617                cbOffset += cbRead;
    593618                if (!cbLeft)
     
    599624    }
    600625    else
    601         VBoxServiceError("ControlExec: Process loop failed with rc=%Rrc\n", rc);
     626        VBoxServiceError("ControlExec: [PID %u]: Loop failed with rc=%Rrc\n",
     627                         pData->uPID, rc);
    602628    return rc;
    603629}
     
    883909                uProcFlags |= RTPROC_FLAGS_SERVICE;
    884910#ifdef DEBUG
    885             VBoxServiceVerbose(3, "Command: %s\n", szExecExp);
     911            VBoxServiceVerbose(3, "ControlExec: Command: %s\n", szExecExp);
    886912            for (size_t i = 0; papszArgsExp[i]; i++)
    887                 VBoxServiceVerbose(3, "\targv[%ld]: %s\n", i, papszArgsExp[i]);
     913                VBoxServiceVerbose(3, "ControlExec:\targv[%ld]: %s\n", i, papszArgsExp[i]);
    888914#endif
    889915            /* Do normal execution. */
     
    10201046                                     * So, NIL the handles to avoid closing them again.
    10211047                                     */
    1022                                     if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, 0 /* stdin */, NULL)))
     1048                                    if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_WRITABLE, NULL)))
    10231049                                        pData->pipeStdInW = NIL_RTPIPE;
    1024                                     if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, 1 /* stdout */, NULL)))
     1050                                    if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_INPUT_NOTIFY, NULL)))
     1051                                        pData->stdIn.hNotificationPipeR = NIL_RTPIPE;
     1052                                    if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, VBOXSERVICECTRLPIPEID_STDOUT, NULL)))
    10251053                                        hStdOutR = NIL_RTPIPE;
    1026                                     if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, 2 /* stderr */, NULL)))
     1054                                    if (RT_FAILURE(RTPollSetQueryHandle(hPollSet, VBOXSERVICECTRLPIPEID_STDERR, NULL)))
    10271055                                        hStdErrR = NIL_RTPIPE;
    10281056                                }
     
    10411069                            }
    10421070                            RTPollSetDestroy(hPollSet);
     1071                            RTPipeClose(pData->stdIn.hNotificationPipeR);
    10431072                        }
    10441073                        RTPipeClose(hStdErrR);
     
    10561085
    10571086    VbglR3GuestCtrlDisconnect(pThread->uClientID);
    1058     VBoxServiceVerbose(3, "ControlExec: Thread of process \"%s\" (PID: %u) ended with rc=%Rrc\n",
    1059                        pData->pszCmd, pData->uPID, rc);
     1087    VBoxServiceVerbose(3, "ControlExec: [PID %u]: Thread of process \"%s\" ended with rc=%Rrc\n",
     1088                       pData->uPID, pData->pszCmd, rc);
    10601089
    10611090    /*
     
    11221151        if (RT_SUCCESS(rc))
    11231152        {
     1153            static uint32_t uCtrlExecThread = 0;
     1154            char szThreadName[32];
     1155            if (!RTStrPrintf(szThreadName, sizeof(szThreadName), "controlexec%ld", uCtrlExecThread++))
     1156                AssertMsgFailed(("Unable to create unique control exec thread name!\n"));
     1157
    11241158            rc = RTThreadCreate(&pThread->Thread, VBoxServiceControlExecThread,
    11251159                                (void *)(PVBOXSERVICECTRLTHREAD*)pThread, 0,
    1126                                 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Exec");
     1160                                RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, szThreadName);
    11271161            if (RT_FAILURE(rc))
    11281162            {
     
    11351169
    11361170                /* Wait for the thread to initialize. */
    1137                 RTThreadUserWait(pThread->Thread, 60 * 1000);
     1171                RTThreadUserWait(pThread->Thread, 60 * 1000 /* 60 seconds max. */);
    11381172                if (pThread->fShutdown)
    11391173                {
     
    12201254    else
    12211255        VBoxServiceError("ControlExec: Failed to retrieve exec start command! Error: %Rrc\n", rc);
    1222     VBoxServiceVerbose(3, "ControlExec: VBoxServiceControlExecHandleCmdStartProcess returned with %Rrc\n", rc);
    12231256    return rc;
    12241257}
     
    12561289    if (RT_FAILURE(rc))
    12571290    {
    1258         VBoxServiceError("ControlExec: Failed to retrieve exec input command! Error: %Rrc\n", rc);
     1291        VBoxServiceError("ControlExec: [PID %u]: Failed to retrieve exec input command! Error: %Rrc\n",
     1292                         uPID, rc);
    12591293    }
    12601294    else if (cbSize >  cbMaxBufSize)
    12611295    {
    1262         VBoxServiceError("ControlExec: Maximum input buffer size is too small! cbSize=%u, cbMaxBufSize=%u\n",
    1263                          cbSize, cbMaxBufSize);
     1296        VBoxServiceError("ControlExec: [PID %u]: Maximum input buffer size is too small! cbSize=%u, cbMaxBufSize=%u\n",
     1297                         uPID, cbSize, cbMaxBufSize);
    12641298        rc = VERR_INVALID_PARAMETER;
    12651299    }
     
    12731307        {
    12741308            fPendingClose = true;
    1275             VBoxServiceVerbose(4, "ControlExec: Got last input block (PID %u) of size %u ...\n",
     1309            VBoxServiceVerbose(4, "ControlExec: [PID %u]: Got last input block of size %u ...\n",
    12761310                               uPID, cbSize);
    12771311        }
     
    12791313        rc = VBoxServiceControlExecThreadSetInput(uPID, fPendingClose, pabBuffer,
    12801314                                                  cbSize, &cbWritten);
    1281         VBoxServiceVerbose(4, "ControlExec: Written input (PID %u): rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n",
     1315        VBoxServiceVerbose(4, "ControlExec: [PID %u]: Written input, rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n",
    12821316                           uPID, rc, uFlags, fPendingClose, cbSize, cbWritten);
    12831317        if (RT_SUCCESS(rc))
     
    13111345    Assert(uStatus > INPUT_STS_UNDEFINED);
    13121346
    1313     VBoxServiceVerbose(3, "ControlExec: Input processed (PID %u), Status=%u, Flags=0x%x, cbWritten=%u\n",
     1347    VBoxServiceVerbose(3, "ControlExec: [PID %u]: Input processed, uStatus=%u, uFlags=0x%x, cbWritten=%u\n",
    13141348                       uPID, uStatus, uFlags, cbWritten);
    13151349
     
    13211355
    13221356    if (RT_FAILURE(rc))
    1323         VBoxServiceError("ControlExec: Failed to report input status! Error: %Rrc\n", rc);
     1357        VBoxServiceError("ControlExec: [PID %u]: Failed to report input status! Error: %Rrc\n",
     1358                         uPID, rc);
    13241359    return rc;
    13251360}
     
    13451380    if (RT_SUCCESS(rc))
    13461381    {
    1347         uint32_t cbRead;
     1382        uint32_t cbRead = 0;
    13481383        uint8_t *pBuf = (uint8_t*)RTMemAlloc(_64K);
    13491384        if (pBuf)
     
    13521387                                                       pBuf, _64K /* cbSize */, &cbRead);
    13531388            if (RT_SUCCESS(rc))
    1354             {
    1355                 VBoxServiceVerbose(3, "ControlExec: Got output (PID %u), read=%u, handle=%u, flags=%u\n",
     1389                VBoxServiceVerbose(3, "ControlExec: [PID %u]: Got output, cbRead=%u, uHandle=%u, uFlags=%u\n",
    13561390                                   uPID, cbRead, uHandleID, uFlags);
    1357 
    1358                 /* Note: Since the context ID is unique the request *has* to be completed here,
    1359                  *       regardless whether we got data or not! Otherwise the progress object
    1360                  *       on the host never will get completed! */
    1361                 /* cbRead now contains actual size. */
    1362                 rc = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, uHandleID, uFlags,
    1363                                                 pBuf, cbRead);
    1364             }
    13651391            else
    1366                 VBoxServiceError("ControlExec: Failed to retrieve output (PID %u), rc=%Rrc\n",
    1367                                  uPID, rc);
     1392                VBoxServiceError("ControlExec: [PID %u]: Failed to retrieve output, uHandle=%u, rc=%Rrc\n",
     1393                                 uPID, uHandleID, rc);
     1394
     1395            /* Note: Since the context ID is unique the request *has* to be completed here,
     1396             *       regardless whether we got data or not! Otherwise the progress object
     1397             *       on the host never will get completed! */
     1398            /* cbRead now contains actual size. */
     1399            int rc2 = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, uHandleID, uFlags,
     1400                                                 pBuf, cbRead);
     1401            if (RT_SUCCESS(rc))
     1402                rc = rc2;
    13681403            RTMemFree(pBuf);
    13691404        }
     
    13711406            rc = VERR_NO_MEMORY;
    13721407    }
    1373     else
    1374         VBoxServiceError("ControlExec: Failed to retrieve exec output command! Error: %Rrc\n", rc);
    1375     return rc;
    1376 }
    1377 
     1408
     1409    if (RT_FAILURE(rc))
     1410        VBoxServiceError("ControlExec: [PID %u]: Failed to handle output command! Error: %Rrc\n",
     1411                         uPID, rc);
     1412    return rc;
     1413}
     1414
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.cpp

    r38085 r38113  
    3636extern RTCRITSECT g_GuestControlExecThreadsCritSect;
    3737
     38const PVBOXSERVICECTRLTHREAD vboxServiceControlExecThreadGetByPID(uint32_t uPID);
    3839
    3940/**
     
    134135
    135136        /* Init buffers. */
    136         rc = VBoxServicePipeBufInit(&pData->stdOut, false /*fNeedNotificationPipe*/);
     137        rc = VBoxServicePipeBufInit(&pData->stdOut, VBOXSERVICECTRLPIPEID_STDOUT,
     138                                    false /*fNeedNotificationPipe*/);
    137139        if (RT_SUCCESS(rc))
    138140        {
    139             rc = VBoxServicePipeBufInit(&pData->stdErr, false /*fNeedNotificationPipe*/);
     141            rc = VBoxServicePipeBufInit(&pData->stdErr, VBOXSERVICECTRLPIPEID_STDERR,
     142                                        false /*fNeedNotificationPipe*/);
    140143            if (RT_SUCCESS(rc))
    141                 rc = VBoxServicePipeBufInit(&pData->stdIn, true /*fNeedNotificationPipe*/);
     144                rc = VBoxServicePipeBufInit(&pData->stdIn, VBOXSERVICECTRLPIPEID_STDIN,
     145                                            true /*fNeedNotificationPipe*/);
     146        }
     147
     148        if (RT_SUCCESS(rc))
     149        {
     150            pThread->enmType = kVBoxServiceCtrlThreadDataExec;
     151            pThread->pvData = pData;
    142152        }
    143153    }
    144154
    145155    if (RT_FAILURE(rc))
    146     {
    147156        VBoxServiceControlExecThreadDestroy(pData);
    148     }
    149     else
    150     {
    151         pThread->enmType = kVBoxServiceCtrlThreadDataExec;
    152         pThread->pvData = pData;
    153     }
    154157    return rc;
    155158}
     
    165168    if (pData)
    166169    {
     170        VBoxServiceVerbose(3, "ControlExec: [PID %u]: Destroying thread ...\n",
     171                           pData->uPID);
     172
    167173        RTStrFree(pData->pszCmd);
    168174        if (pData->uNumEnvVars)
     
    186192
    187193
     194int VBoxServiceControlExecThreadAssignPID(PVBOXSERVICECTRLTHREADDATAEXEC pData, uint32_t uPID)
     195{
     196    AssertPtrReturn(pData, VERR_INVALID_POINTER);
     197    AssertReturn(uPID, VERR_INVALID_PARAMETER);
     198
     199    int rc = RTCritSectEnter(&g_GuestControlExecThreadsCritSect);
     200    if (RT_SUCCESS(rc))
     201    {
     202        /* Search an old thread using the desired PID and shut it down completely -- it's
     203         * not used anymore. */
     204        const PVBOXSERVICECTRLTHREAD pOldThread = vboxServiceControlExecThreadGetByPID(uPID);
     205        if (   pOldThread
     206            && pOldThread->pvData != pData)
     207        {
     208            VBoxServiceVerbose(3, "ControlExec: PID %u was used before, shutting down stale exec thread ...\n",
     209                               uPID);
     210            AssertPtr(pOldThread->pvData);
     211            VBoxServiceControlExecThreadDestroy((PVBOXSERVICECTRLTHREADDATAEXEC)pOldThread->pvData);
     212        }
     213        /** @todo Remove node from thread list! */
     214
     215        /* Assign PID to current thread. */
     216        pData->uPID = uPID;
     217        VBoxServicePipeBufSetPID(&pData->stdIn, pData->uPID);
     218        VBoxServicePipeBufSetPID(&pData->stdOut, pData->uPID);
     219        VBoxServicePipeBufSetPID(&pData->stdErr, pData->uPID);
     220
     221        int rc2 = RTCritSectLeave(&g_GuestControlExecThreadsCritSect);
     222        if (RT_SUCCESS(rc))
     223            rc = rc2;
     224    }
     225
     226    return rc;
     227}
     228
     229
    188230/**
    189231 * Finds a (formerly) started process given by its PID.
     
    193235 * @param   uPID                        PID to search for.
    194236 */
    195 PVBOXSERVICECTRLTHREAD vboxServiceControlExecThreadGetByPID(uint32_t uPID)
     237const PVBOXSERVICECTRLTHREAD vboxServiceControlExecThreadGetByPID(uint32_t uPID)
    196238{
    197239    PVBOXSERVICECTRLTHREAD pNode = NULL;
     
    236278            if (VBoxServicePipeBufIsEnabled(&pData->stdIn))
    237279            {
    238                 uint32_t cbWritten;
    239280                /*
    240281                 * Feed the data to the pipe.
    241282                 */
     283                uint32_t cbWritten;
    242284                rc = VBoxServicePipeBufWriteToBuf(&pData->stdIn, pBuf,
    243285                                                  cbSize, fPendingClose, &cbWritten);
     
    279321    if (RT_SUCCESS(rc))
    280322    {
    281         PVBOXSERVICECTRLTHREAD pNode = vboxServiceControlExecThreadGetByPID(uPID);
     323        const PVBOXSERVICECTRLTHREAD pNode = vboxServiceControlExecThreadGetByPID(uPID);
    282324        if (pNode)
    283325        {
    284             PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData;
     326            const PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData;
    285327            AssertPtr(pData);
    286328
    287             PVBOXSERVICECTRLEXECPIPEBUF pPipeBuf;
     329            PVBOXSERVICECTRLEXECPIPEBUF pPipeBuf = NULL;
    288330            switch (uHandleId)
    289331            {
     
    293335
    294336                case OUTPUT_HANDLE_ID_STDOUT: /* StdOut */
     337                    pPipeBuf = &pData->stdOut;
     338                    break;
     339
    295340                default:
    296                     pPipeBuf = &pData->stdOut;
    297                     break;
    298             }
    299             AssertPtr(pPipeBuf);
    300 
     341                    AssertReleaseMsgFailed(("Unknown output handle ID (%u)\n", uHandleId));
     342                    break;
     343            }
     344            if (!pPipeBuf)
     345                return VERR_INVALID_PARAMETER;
     346
     347#ifdef DEBUG_andy
     348            VBoxServiceVerbose(4, "ControlExec: [PID %u]: Getting output from pipe buffer %u ...\n",
     349                               uPID, pPipeBuf->uPipeId);
     350#endif
    301351            /* If the stdout pipe buffer is enabled (that is, still could be filled by a running
    302352             * process) wait for the signal to arrive so that we don't return without any actual
    303353             * data read. */
    304             if (VBoxServicePipeBufIsEnabled(pPipeBuf))
     354            bool fEnabled = VBoxServicePipeBufIsEnabled(pPipeBuf);
     355            if (fEnabled)
     356            {
     357#ifdef DEBUG_andy
     358                VBoxServiceVerbose(4, "ControlExec: [PID %u]: Waiting for pipe buffer %u\n",
     359                                   uPID, pPipeBuf->uPipeId);
     360#endif
    305361                rc = VBoxServicePipeBufWaitForEvent(pPipeBuf, uTimeout);
    306 
     362            }
    307363            if (RT_SUCCESS(rc))
    308364            {
     
    311367                if (RT_SUCCESS(rc))
    312368                {
     369                    if (fEnabled && !cbRead)
     370                        AssertMsgFailed(("Waited for pipe buffer %u, but nothing read!\n",
     371                                         pPipeBuf->uPipeId));
    313372                    if (pcbRead)
    314373                        *pcbRead = cbRead;
    315374                }
     375                else
     376                    VBoxServiceError("ControlExec: [PID %u]: Unable to read from pipe buffer %u, rc=%Rrc\n",
     377                                     uPID, pPipeBuf->uPipeId, rc);
    316378            }
    317379        }
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExecThread.h

    r36548 r38113  
    2727                                      const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
    2828                                      const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS);
     29int VBoxServiceControlExecThreadAssignPID(PVBOXSERVICECTRLTHREADDATAEXEC pData, uint32_t uPID);
    2930void VBoxServiceControlExecThreadDestroy(PVBOXSERVICECTRLTHREADDATAEXEC pData);
    3031int VBoxServiceControlExecThreadSetInput(uint32_t uPID, bool fPendingClose, uint8_t *pBuf,
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r37375 r38113  
    102102# define VBOXSERVICE_FRIENDLY_NAME  "VirtualBox Guest Additions Service"
    103103/** The service description (only W2K+ atm) */
    104 # define VBOXSERVICE_DESCRIPTION    "Manages VM runtime information, time synchronization, remote sysprep execution and miscellaneous utilities for guest operating systems."
     104# define VBOXSERVICE_DESCRIPTION    "Manages VM runtime information, time synchronization, guest control execution and miscellaneous utilities for guest operating systems."
    105105/** The following constant may be defined by including NtStatus.h. */
    106106# define STATUS_SUCCESS             ((NTSTATUS)0x00000000L)
     
    116116typedef enum VBOXSERVICECTRLPIPEID
    117117{
    118     VBOXSERVICECTRLPIPEID_STDIN_ERROR  = 0,
     118    VBOXSERVICECTRLPIPEID_STDIN = 0,
     119    VBOXSERVICECTRLPIPEID_STDIN_ERROR,
    119120    VBOXSERVICECTRLPIPEID_STDIN_WRITABLE,
    120121    VBOXSERVICECTRLPIPEID_STDIN_INPUT_NOTIFY,
     
    128129typedef struct
    129130{
     131    /** The PID the pipe is assigned to. */
     132    uint32_t    uPID;
     133    /** The pipe's Id of enum VBOXSERVICECTRLPIPEID. */
     134    uint8_t     uPipeId;
    130135    /** The data buffer. */
    131136    uint8_t    *pbData;
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServicePipeBuf.cpp

    r38085 r38113  
    2828#include "VBoxServicePipeBuf.h"
    2929
    30 
    3130/**
    3231 * Initializes a pipe buffer.
     
    3433 * @returns IPRT status code.
    3534 * @param   pBuf                    The pipe buffer to initialize.
     35 * @param   uId                     The pipe's ID handle.
    3636 * @param   fNeedNotificationPipe   Whether the buffer needs a notification
    3737 *                                  pipe or not.
    3838 */
    39 int VBoxServicePipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe)
     39int VBoxServicePipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, uint8_t uId, bool fNeedNotificationPipe)
    4040{
    4141    AssertPtrReturn(pBuf, VERR_INVALID_POINTER);
    4242
    4343    /** @todo Add allocation size as function parameter! */
     44    pBuf->uPID = 0; /* We don't have the PID yet. */
     45    pBuf->uPipeId = uId;
    4446    pBuf->pbData = (uint8_t *)RTMemAlloc(_64K); /* Start with a 64k buffer. */
    4547    AssertReturn(pBuf->pbData, VERR_NO_MEMORY);
     
    5961        rc = RTCritSectInit(&pBuf->CritSect);
    6062        if (RT_SUCCESS(rc) && fNeedNotificationPipe)
    61         {
    6263            rc = RTPipeCreate(&pBuf->hNotificationPipeR, &pBuf->hNotificationPipeW, 0);
    63             if (RT_FAILURE(rc))
    64             {
    65                 RTCritSectDelete(&pBuf->CritSect);
    66                 if (pBuf->hEventSem != NIL_RTSEMEVENT)
    67                     RTSemEventDestroy(pBuf->hEventSem);
    68             }
    69         }
     64    }
     65
     66    if (RT_FAILURE(rc))
     67    {
     68        if (RTCritSectIsInitialized(&pBuf->CritSect))
     69            RTCritSectDelete(&pBuf->CritSect);
     70        if (pBuf->hEventSem != NIL_RTSEMEVENT)
     71            RTSemEventDestroy(pBuf->hEventSem);
    7072    }
    7173    return rc;
     
    9698    {
    9799        Assert(pBuf->cbSize >= pBuf->cbOffset);
    98         if (*pcbToRead > pBuf->cbSize - pBuf->cbOffset)
    99             *pcbToRead = pBuf->cbSize - pBuf->cbOffset;
    100 
    101         if (*pcbToRead > cbBuffer)
    102             *pcbToRead = cbBuffer;
    103 
    104         if (*pcbToRead > 0)
    105         {
    106             memcpy(pbBuffer, pBuf->pbData + pBuf->cbOffset, *pcbToRead);
    107             pBuf->cbOffset += *pcbToRead;
     100        uint32_t cbToRead = *pcbToRead;
     101
     102        if (cbToRead > pBuf->cbSize - pBuf->cbOffset)
     103            cbToRead = pBuf->cbSize - pBuf->cbOffset;
     104
     105        if (cbToRead > cbBuffer)
     106            cbToRead = cbBuffer;
     107
     108        if (cbToRead)
     109        {
     110            memcpy(pbBuffer, &pBuf->pbData[pBuf->cbOffset], cbToRead);
     111            pBuf->cbOffset += cbToRead;
    108112
    109113            if (pBuf->hEventSem != NIL_RTSEMEVENT)
     
    114118
    115119#ifdef DEBUG_andy
    116             VBoxServiceVerbose(4, "PipeBuf[0x%p]: read=%u, size=%u, alloc=%u, off=%u\n",
    117                                    pBuf, *pcbToRead, pBuf->cbSize, pBuf->cbAllocated, pBuf->cbOffset);
     120            VBoxServiceVerbose(4, "Pipe [%u %u 0x%p %s] read pcbToRead=%u, cbSize=%u, cbAlloc=%u, cbOff=%u\n",
     121                               pBuf->uPID, pBuf->uPipeId, pBuf, pBuf->fEnabled ? "EN" : "DIS", cbToRead, pBuf->cbSize, pBuf->cbAllocated, pBuf->cbOffset);
    118122#endif
     123            *pcbToRead = cbToRead;
    119124        }
    120125        else
    121126        {
    122             pbBuffer = NULL;
    123127            *pcbToRead = 0;
    124128        }
     
    132136
    133137
     138/**
     139 * Peeks for buffer data without moving the buffer's offset
     140 * or touching any other internal data.
     141 *
     142 * @return  IPRT status code.
     143 * @param   pBuf                        Pointer to pipe buffer to read the data from.
     144 * @param   pbBuffer                    Pointer to buffer to store the read out data.
     145 * @param   cbBuffer                    Size (in bytes) of the buffer where to store the data.
     146 * @param   cbOffset                    Offset (in bytes) where to start reading.
     147 * @param   pcbRead                     Pointer to desired amount (in bytes) of data to read,
     148 *                                      will reflect the actual amount read on return.
     149 * @param   pcbLeft                     Pointer to bytes left in buffer after the current read
     150 *                                      operation.
     151 */
    134152int VBoxServicePipeBufPeek(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
    135153                           uint8_t *pbBuffer, uint32_t cbBuffer,
     
    140158    AssertPtrReturn(pbBuffer, VERR_INVALID_POINTER);
    141159    AssertReturn(cbBuffer, VERR_INVALID_PARAMETER);
    142 
    143     int rc = RTCritSectEnter(&pBuf->CritSect);
    144     if (RT_SUCCESS(rc))
    145     {
    146         Assert(pBuf->cbSize >= pBuf->cbOffset);
     160    AssertReturn(pBuf->cbSize >= pBuf->cbOffset, VERR_BUFFER_OVERFLOW);
     161
     162    int rc = RTCritSectEnter(&pBuf->CritSect);
     163    if (RT_SUCCESS(rc))
     164    {
    147165        if (cbOffset > pBuf->cbSize)
    148166            cbOffset = pBuf->cbSize;
     
    152170        if (cbToRead)
    153171        {
    154             memcpy(pbBuffer, pBuf->pbData + cbOffset, cbToRead);
     172            memcpy(pbBuffer, &pBuf->pbData[cbOffset], cbToRead);
    155173            pbBuffer[cbBuffer - 1] = '\0';
    156174        }
     
    183201{
    184202    AssertPtrReturn(pBuf, VERR_INVALID_POINTER);
    185 
    186     int rc = RTCritSectEnter(&pBuf->CritSect);
    187     if (RT_SUCCESS(rc))
    188     {
    189         AssertPtrReturn(pbData, VERR_INVALID_POINTER);
     203    AssertPtrReturn(pbData, VERR_INVALID_POINTER);
     204
     205    int rc = RTCritSectEnter(&pBuf->CritSect);
     206    if (RT_SUCCESS(rc))
     207    {
    190208        if (pBuf->fEnabled)
    191209        {
     
    269287                    *pcbWritten = cbData;
    270288
    271                 if (pBuf->hEventSem != NIL_RTSEMEVENT)
     289                /* Only trigger signal if we really wrote something. */
     290                if (   cbData
     291                    && pBuf->hEventSem != NIL_RTSEMEVENT)
    272292                {
    273293                    rc = RTSemEventSignal(pBuf->hEventSem);
     
    276296
    277297#ifdef DEBUG_andy
    278                 VBoxServiceVerbose(4, "PipeBuf[0x%p]: written=%u, size=%u, alloc=%u, off=%u\n",
    279                                    pBuf, cbData, pBuf->cbSize, pBuf->cbAllocated, pBuf->cbOffset);
     298                VBoxServiceVerbose(4, "Pipe [%u %u 0x%p %s] written cbData=%u, cbSize=%u, cbAlloc=%u, cbOff=%u\n",
     299                                   pBuf->uPID, pBuf->uPipeId, pBuf, pBuf->fEnabled ? "EN" : "DIS", cbData, pBuf->cbSize, pBuf->cbAllocated, pBuf->cbOffset);
    280300#endif
    281301            }
     
    349369            {
    350370                *pcbWritten = 0;
    351                 pBuf->fEnabled = false;
     371                /* Don't set pBuf->fEnabled to false here! We just didn't write
     372                 * anything -- that doesn't mean this buffer is disabled (again). */
    352373            }
    353374        }
     
    377398
    378399    bool fEnabled = false;
    379     if (   RTCritSectIsInitialized(&pBuf->CritSect)
    380         && RT_SUCCESS(RTCritSectEnter(&pBuf->CritSect)))
     400    int rc = RTCritSectEnter(&pBuf->CritSect);
     401    if (RT_SUCCESS(rc))
    381402    {
    382403        fEnabled = pBuf->fEnabled;
     
    400421    AssertPtrReturn(pBuf, false);
    401422
     423    if (!RTCritSectIsInitialized(&pBuf->CritSect))
     424        return false;
     425
    402426    bool fClosing = false;
    403     if (   RTCritSectIsInitialized(&pBuf->CritSect)
    404         && RT_SUCCESS(RTCritSectEnter(&pBuf->CritSect)))
     427    if (RT_SUCCESS(RTCritSectEnter(&pBuf->CritSect)))
    405428    {
    406429        fClosing = pBuf->fPendingClose;
     
    425448    if (RT_SUCCESS(rc))
    426449    {
     450        bool fEnabledOld = pBuf->fEnabled;
    427451        pBuf->fEnabled = fEnabled;
    428         /* Let waiter know that something has changed ... */
    429         if (pBuf->hEventSem)
     452        if (   pBuf->fEnabled != fEnabledOld
     453            && pBuf->hEventSem)
     454        {
     455            /* Let waiter know that something has changed ... */
    430456            RTSemEventSignal(pBuf->hEventSem);
     457        }
    431458        rc = RTCritSectLeave(&pBuf->CritSect);
    432459    }
     
    435462
    436463
     464/**
     465 * Assigns a PID to the specified pipe buffer. Does not allow
     466 * setting a new PID after a PID already was set.
     467 *
     468 * @return  IPRT status code.
     469 * @param   pBuf            The pipe buffer.
     470 * @param   uPID            PID to assign.
     471 */
     472int VBoxServicePipeBufSetPID(PVBOXSERVICECTRLEXECPIPEBUF pBuf, uint32_t uPID)
     473{
     474    AssertPtrReturn(pBuf, VERR_INVALID_POINTER);
     475
     476    int rc = RTCritSectEnter(&pBuf->CritSect);
     477    if (RT_SUCCESS(rc))
     478    {
     479        if (!pBuf->uPID)
     480            pBuf->uPID = uPID;
     481        rc = RTCritSectLeave(&pBuf->CritSect);
     482    }
     483    return rc;
     484}
     485
     486
     487/**
     488 * Waits for the pipe buffer to get notified when something changed, like
     489 * new data was written to or the buffer was disabled, i.e. not used anymore.
     490 *
     491 * @return  IPRT status code.
     492 * @param   pBuf            The pipe buffer.
     493 * @param   cMillies        The maximum time (in ms) to wait for the event.
     494 */
    437495int VBoxServicePipeBufWaitForEvent(PVBOXSERVICECTRLEXECPIPEBUF pBuf, RTMSINTERVAL cMillies)
    438496{
     
    455513void VBoxServicePipeBufDestroy(PVBOXSERVICECTRLEXECPIPEBUF pBuf)
    456514{
    457     AssertPtr(pBuf);
     515    AssertPtrReturnVoid(pBuf);
     516
    458517    if (pBuf->pbData)
    459518    {
    460         RTMemFree(pBuf->pbData);
    461         pBuf->pbData = NULL;
     519        pBuf->uPID = 0;
     520        pBuf->uPipeId = 0;
    462521        pBuf->cbAllocated = 0;
    463522        pBuf->cbSize = 0;
    464523        pBuf->cbOffset = 0;
    465     }
    466 
    467     RTPipeClose(pBuf->hNotificationPipeR);
    468     pBuf->hNotificationPipeR = NIL_RTPIPE;
    469     RTPipeClose(pBuf->hNotificationPipeW);
    470     pBuf->hNotificationPipeW = NIL_RTPIPE;
    471 
    472     RTCritSectDelete(&pBuf->CritSect);
    473     if (pBuf->hEventSem != NIL_RTSEMEVENT)
    474         RTSemEventDestroy(pBuf->hEventSem);
    475 }
    476 
     524
     525        RTPipeClose(pBuf->hNotificationPipeR);
     526        pBuf->hNotificationPipeR = NIL_RTPIPE;
     527        RTPipeClose(pBuf->hNotificationPipeW);
     528        pBuf->hNotificationPipeW = NIL_RTPIPE;
     529
     530        if (RTCritSectIsInitialized(&pBuf->CritSect))
     531            RTCritSectDelete(&pBuf->CritSect);
     532        if (pBuf->hEventSem != NIL_RTSEMEVENT)
     533            RTSemEventDestroy(pBuf->hEventSem);
     534
     535        RTMemFree(pBuf->pbData);
     536        pBuf->pbData = NULL;
     537    }
     538}
     539
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServicePipeBuf.h

    r36744 r38113  
    2121#include "VBoxServiceInternal.h"
    2222
    23 int  VBoxServicePipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe);
     23int  VBoxServicePipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, uint8_t uId, bool fNeedNotificationPipe);
    2424int  VBoxServicePipeBufRead(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
    2525                            uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead);
     
    3434bool VBoxServicePipeBufIsEnabled(PVBOXSERVICECTRLEXECPIPEBUF pBuf);
    3535bool VBoxServicePipeBufIsClosing(PVBOXSERVICECTRLEXECPIPEBUF pBuf);
     36int  VBoxServicePipeBufSetPID(PVBOXSERVICECTRLEXECPIPEBUF pBuf, uint32_t uPID);
    3637int  VBoxServicePipeBufSetStatus(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fEnabled);
    3738int  VBoxServicePipeBufWaitForEvent(PVBOXSERVICECTRLEXECPIPEBUF pBuf, RTMSINTERVAL cMillies);
Note: See TracChangeset for help on using the changeset viewer.

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