VirtualBox

vbox的更動 36548 路徑 trunk/src


忽略:
時間撮記:
2011-4-5 上午09:27:33 (14 年 以前)
作者:
vboxsync
訊息:

VBoxService/GuestCopy: Fixed copying of small and 0-byte files. Refactored per-process threading code into own module, added thread locking/access.

位置:
trunk/src/VBox/Additions/common/VBoxService
檔案:
新增 2 筆資料
修改 4 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/Additions/common/VBoxService/Makefile.kmk

    r36305 r36548  
    55
    66#
    7 # Copyright (C) 2007-2010 Oracle Corporation
     7# Copyright (C) 2007-2011 Oracle Corporation
    88#
    99# This file is part of VirtualBox Open Source Edition (OSE), as
     
    7070        VBoxServiceControl.cpp \
    7171        VBoxServiceControlExec.cpp \
     72        VBoxServiceControlExecThread.cpp \
    7273        VBoxServicePipeBuf.cpp
    7374endif
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp

    r35060 r36548  
    55
    66/*
    7  * Copyright (C) 2010 Oracle Corporation
     7 * Copyright (C) 2011 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2020*   Header Files                                                               *
    2121*******************************************************************************/
    22 #include <iprt/asm.h>
    2322#include <iprt/assert.h>
    2423#include <iprt/getopt.h>
     
    3029#include "VBoxServiceInternal.h"
    3130#include "VBoxServiceUtils.h"
     31#include "VBoxServiceControlExecThread.h"
    3232
    3333using namespace guestControl;
     
    4242/** The Guest Control service client ID. */
    4343static uint32_t             g_GuestControlSvcClientID = 0;
    44 /** List of spawned processes */
     44/** List of spawned processes. */
    4545RTLISTNODE                  g_GuestControlExecThreads;
    46 
     46/** Critical section protecting g_GuestControlExecThreads. */
     47RTCRITSECT                  g_GuestControlExecThreadsCritSect;
    4748
    4849/** @copydoc VBOXSERVICE::pfnPreInit */
     
    8687        /* Init thread list. */
    8788        RTListInit(&g_GuestControlExecThreads);
     89        rc = RTCritSectInit(&g_GuestControlExecThreadsCritSect);
     90        AssertRC(rc);
    8891    }
    8992    else
     
    216219    VBoxServiceVerbose(3, "Control: Terminating ...\n");
    217220
    218     /* Signal all threads that we want to shutdown. */
    219     PVBOXSERVICECTRLTHREAD pNode;
    220     RTListForEach(&g_GuestControlExecThreads, pNode, VBOXSERVICECTRLTHREAD, Node)
    221         ASMAtomicXchgBool(&pNode->fShutdown, true);
    222 
    223     /* Wait for threads to shutdown. */
    224     RTListForEach(&g_GuestControlExecThreads, pNode, VBOXSERVICECTRLTHREAD, Node)
    225     {
    226         if (pNode->Thread != NIL_RTTHREAD)
    227         {
    228             /* Wait a bit ... */
    229             int rc2 = RTThreadWait(pNode->Thread, 30 * 1000 /* Wait 30 seconds max. */, NULL);
    230             if (RT_FAILURE(rc2))
    231                 VBoxServiceError("Control: Thread failed to stop; rc2=%Rrc\n", rc2);
    232         }
    233 
    234         /* Destroy thread specific data. */
    235         switch (pNode->enmType)
    236         {
    237             case kVBoxServiceCtrlThreadDataExec:
    238                 VBoxServiceControlExecDestroyThreadData((PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData);
    239                 break;
    240 
    241             default:
    242                 break;
    243         }
    244     }
    245 
    246     /* Finally destroy thread list. */
    247     pNode = RTListGetFirst(&g_GuestControlExecThreads, VBOXSERVICECTRLTHREAD, Node);
    248     while (pNode)
    249     {
    250         PVBOXSERVICECTRLTHREAD pNext = RTListNodeGetNext(&pNode->Node, VBOXSERVICECTRLTHREAD, Node);
    251         bool fLast = RTListNodeIsLast(&g_GuestControlExecThreads, &pNode->Node);
    252 
    253         RTListNodeRemove(&pNode->Node);
    254         RTMemFree(pNode);
    255 
    256         if (fLast)
    257             break;
    258 
    259         pNode = pNext;
    260     }
     221    VBoxServiceControlExecThreadsShutdown();
    261222
    262223    VbglR3GuestCtrlDisconnect(g_GuestControlSvcClientID);
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp

    r36305 r36548  
    4343#include "VBoxServiceUtils.h"
    4444#include "VBoxServicePipeBuf.h"
     45#include "VBoxServiceControlExecThread.h"
    4546
    4647using namespace guestControl;
    4748
    4849extern RTLISTNODE g_GuestControlExecThreads;
     50extern RTCRITSECT g_GuestControlExecThreadsCritSect;
    4951
    5052
     
    8082    /* Remove stdin error handle from set. */
    8183    rc = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_ERROR);
    82     AssertRC(rc);
     84    /* Don't assert if writable handle is not in poll set anymore. */
     85    if (   RT_FAILURE(rc)
     86        && rc != VERR_POLL_HANDLE_ID_NOT_FOUND)
     87    {
     88        AssertRC(rc);
     89    }
     90    else
     91        rc = VINF_SUCCESS;
    8392
    8493    return rc;
     
    182191
    183192/**
    184  * Handle a transport event or successful pfnPollIn() call.
    185  *
    186  * @returns IPRT status code from client send.
    187  * @retval  VINF_EOF indicates ABORT command.
    188  *
    189  * @param   hPollSet            The polling set.
    190  * @param   fPollEvt            The event mask returned by RTPollNoResume.
    191  * @param   idPollHnd           The handle ID.
    192  * @param   hStdInW             The standard input pipe.
    193  * @param   pStdInBuf           The standard input buffer.
    194  */
    195 static int VBoxServiceControlExecProcHandleTransportEvent(RTPOLLSET hPollSet, uint32_t fPollEvt, uint32_t idPollHnd,
    196                                                           PRTPIPE phStdInW, PVBOXSERVICECTRLEXECPIPEBUF pStdInBuf)
    197 {
    198     return 0; //RTPollSetAddPipe(hPollSet, *phStdInW, RTPOLL_EVT_WRITE, 4 /*TXSEXECHNDID_STDIN_WRITABLE*/);
    199 }
    200 
    201 
    202 /**
    203193 * Handle pending output data or error on standard out, standard error or the
    204194 * test pipe.
     
    290280
    291281/**
    292  * Execution loop which (usually) runs in a dedicated per-started-process thread and
     282 * Execution loop which runs in a dedicated per-started-process thread and
    293283 * handles all pipe input/output and signalling stuff.
    294284 *
     
    637627
    638628    return rc;
    639 }
    640 
    641 
    642 /**
    643  *  Allocates and gives back a thread data struct which then can be used by the worker thread.
    644  *  Needs to be freed with VBoxServiceControlExecDestroyThreadData().
    645  *
    646  * @return  IPRT status code.
    647  * @param   pThread                     The thread's handle to allocate the data for.
    648  * @param   u32ContextID                The context ID bound to this request / command.
    649  * @param   pszCmd                      Full qualified path of process to start (without arguments).
    650  * @param   uFlags                      Process execution flags.
    651  * @param   pszArgs                     String of arguments to pass to the process to start.
    652  * @param   uNumArgs                    Number of arguments specified in pszArgs.
    653  * @param   pszEnv                      String of environment variables ("FOO=BAR") to pass to the process
    654  *                                      to start.
    655  * @param   cbEnv                       Size (in bytes) of environment variables.
    656  * @param   uNumEnvVars                 Number of environment variables specified in pszEnv.
    657  * @param   pszUser                     User name (account) to start the process under.
    658  * @param   pszPassword                 Password of specified user name (account).
    659  * @param   uTimeLimitMS                Time limit (in ms) of the process' life time.
    660  */
    661 static int VBoxServiceControlExecAllocateThreadData(PVBOXSERVICECTRLTHREAD pThread,
    662                                                     uint32_t u32ContextID,
    663                                                     const char *pszCmd, uint32_t uFlags,
    664                                                     const char *pszArgs, uint32_t uNumArgs,
    665                                                     const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
    666                                                     const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS)
    667 {
    668     AssertPtr(pThread);
    669 
    670     /* General stuff. */
    671     pThread->Node.pPrev = NULL;
    672     pThread->Node.pNext = NULL;
    673 
    674     pThread->fShutdown = false;
    675     pThread->fStarted = false;
    676     pThread->fStopped = false;
    677 
    678     pThread->uContextID = u32ContextID;
    679     /* ClientID will be assigned when thread is started! */
    680 
    681     /* Specific stuff. */
    682     PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)RTMemAlloc(sizeof(VBOXSERVICECTRLTHREADDATAEXEC));
    683     if (pData == NULL)
    684         return VERR_NO_MEMORY;
    685 
    686     pData->uPID = 0; /* Don't have a PID yet. */
    687     pData->pszCmd = RTStrDup(pszCmd);
    688     pData->uFlags = uFlags;
    689     pData->uNumEnvVars = 0;
    690     pData->uNumArgs = 0; /* Initialize in case of RTGetOptArgvFromString() is failing ... */
    691 
    692     /* Prepare argument list. */
    693     int rc = RTGetOptArgvFromString(&pData->papszArgs, (int*)&pData->uNumArgs,
    694                                     (uNumArgs > 0) ? pszArgs : "", NULL);
    695     /* Did we get the same result? */
    696     Assert(uNumArgs == pData->uNumArgs);
    697 
    698     if (RT_SUCCESS(rc))
    699     {
    700         /* Prepare environment list. */
    701         if (uNumEnvVars)
    702         {
    703             pData->papszEnv = (char **)RTMemAlloc(uNumEnvVars * sizeof(char*));
    704             AssertPtr(pData->papszEnv);
    705             pData->uNumEnvVars = uNumEnvVars;
    706 
    707             const char *pszCur = pszEnv;
    708             uint32_t i = 0;
    709             uint32_t cbLen = 0;
    710             while (cbLen < cbEnv)
    711             {
    712                 /* sanity check */
    713                 if (i >= uNumEnvVars)
    714                 {
    715                     rc = VERR_INVALID_PARAMETER;
    716                     break;
    717                 }
    718                 int cbStr = RTStrAPrintf(&pData->papszEnv[i++], "%s", pszCur);
    719                 if (cbStr < 0)
    720                 {
    721                     rc = VERR_NO_STR_MEMORY;
    722                     break;
    723                 }
    724                 pszCur += cbStr + 1; /* Skip terminating '\0' */
    725                 cbLen  += cbStr + 1; /* Skip terminating '\0' */
    726             }
    727         }
    728 
    729         pData->pszUser = RTStrDup(pszUser);
    730         pData->pszPassword = RTStrDup(pszPassword);
    731         pData->uTimeLimitMS = uTimeLimitMS;
    732 
    733         /* Adjust time limit value. */
    734         pData->uTimeLimitMS = (   uTimeLimitMS == UINT32_MAX
    735                                || uTimeLimitMS == 0)
    736                             ? RT_INDEFINITE_WAIT : uTimeLimitMS;
    737 
    738         /* Init buffers. */
    739         rc = VBoxServicePipeBufInit(&pData->stdOut, false /*fNeedNotificationPipe*/);
    740         if (RT_SUCCESS(rc))
    741         {
    742             rc = VBoxServicePipeBufInit(&pData->stdErr, false /*fNeedNotificationPipe*/);
    743             if (RT_SUCCESS(rc))
    744                 rc = VBoxServicePipeBufInit(&pData->stdIn, true /*fNeedNotificationPipe*/);
    745         }
    746     }
    747 
    748     if (RT_FAILURE(rc))
    749     {
    750         VBoxServiceControlExecDestroyThreadData(pData);
    751     }
    752     else
    753     {
    754         pThread->enmType = kVBoxServiceCtrlThreadDataExec;
    755         pThread->pvData = pData;
    756     }
    757     return rc;
    758 }
    759 
    760 
    761 /**
    762  *  Frees an allocated thread data structure along with all its allocated parameters.
    763  *
    764  * @param   pData          Pointer to thread data to free.
    765  */
    766 void VBoxServiceControlExecDestroyThreadData(PVBOXSERVICECTRLTHREADDATAEXEC pData)
    767 {
    768     if (pData)
    769     {
    770         RTStrFree(pData->pszCmd);
    771         if (pData->uNumEnvVars)
    772         {
    773             for (uint32_t i = 0; i < pData->uNumEnvVars; i++)
    774                 RTStrFree(pData->papszEnv[i]);
    775             RTMemFree(pData->papszEnv);
    776         }
    777         RTGetOptArgvFree(pData->papszArgs);
    778         RTStrFree(pData->pszUser);
    779         RTStrFree(pData->pszPassword);
    780 
    781         VBoxServicePipeBufDestroy(&pData->stdOut);
    782         VBoxServicePipeBufDestroy(&pData->stdErr);
    783         VBoxServicePipeBufDestroy(&pData->stdIn);
    784 
    785         RTMemFree(pData);
    786         pData = NULL;
    787     }
    788629}
    789630
     
    12181059
    12191060/**
    1220  * Finds a (formerly) started process given by its PID.
    1221  *
    1222  * @return  PVBOXSERVICECTRLTHREAD      Process structure if found, otherwise NULL.
    1223  * @param   uPID                        PID to search for.
    1224  */
    1225 static PVBOXSERVICECTRLTHREAD VBoxServiceControlExecFindProcess(uint32_t uPID)
    1226 {
    1227     PVBOXSERVICECTRLTHREAD pNode;
    1228     bool fFound = false;
    1229     RTListForEach(&g_GuestControlExecThreads, pNode, VBOXSERVICECTRLTHREAD, Node)
    1230     {
    1231         if (   pNode->fStarted
    1232             && pNode->enmType == kVBoxServiceCtrlThreadDataExec)
    1233         {
    1234             PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData;
    1235             if (pData && pData->uPID == uPID)
    1236             {
    1237                 return pNode;
    1238             }
    1239         }
    1240     }
    1241     return NULL;
    1242 }
    1243 
    1244 
    1245 /**
    12461061 * Thread main routine for a started process.
    12471062 *
     
    12821097                                  const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS)
    12831098{
     1099    int rc;
     1100
    12841101    PVBOXSERVICECTRLTHREAD pThread = (PVBOXSERVICECTRLTHREAD)RTMemAlloc(sizeof(VBOXSERVICECTRLTHREAD));
    1285 
    1286     int rc;
    12871102    if (pThread)
    12881103    {
    1289         rc = VBoxServiceControlExecAllocateThreadData(pThread,
    1290                                                       uContextID,
    1291                                                       pszCmd, uFlags,
    1292                                                       pszArgs, uNumArgs,
    1293                                                       pszEnv, cbEnv, uNumEnvVars,
    1294                                                       pszUser, pszPassword,
    1295                                                       uTimeLimitMS);
     1104        rc = VBoxServiceControlExecThreadAlloc(pThread,
     1105                                               uContextID,
     1106                                               pszCmd, uFlags,
     1107                                               pszArgs, uNumArgs,
     1108                                               pszEnv, cbEnv, uNumEnvVars,
     1109                                               pszUser, pszPassword,
     1110                                               uTimeLimitMS);
    12961111        if (RT_SUCCESS(rc))
    12971112        {
     
    13231138
    13241139            if (RT_FAILURE(rc))
    1325                 VBoxServiceControlExecDestroyThreadData((PVBOXSERVICECTRLTHREADDATAEXEC)pThread->pvData);
     1140                VBoxServiceControlExecThreadDestroy((PVBOXSERVICECTRLTHREADDATAEXEC)pThread->pvData);
    13261141        }
    13271142        if (RT_FAILURE(rc))
     
    14191234    AssertPtrReturn(pabBuffer, VERR_NO_MEMORY);
    14201235
     1236    uint32_t uStatus = INPUT_STS_UNDEFINED; /* Status sent back to the host. */
     1237    uint32_t cbWritten = 0; /* Number of bytes written to the guest. */
     1238
    14211239    /*
    14221240     * Ask the host for the input data.
     
    14381256    {
    14391257        /*
    1440          * Resolve the PID.
     1258         * Is this the last input block we need to deliver? Then let the pipe know ...
    14411259         */
    1442         VBoxServiceVerbose(4, "ControlExec: Input (PID %u) received: cbSize=%u\n", uPID, cbSize);
    1443 
    1444         PVBOXSERVICECTRLTHREAD pNode = VBoxServiceControlExecFindProcess(uPID);
    1445         if (pNode)
    1446         {
    1447             PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData;
    1448             AssertPtr(pData);
    1449 
    1450             /*
    1451              * Is this the last input block we need to deliver? Then let the pipe know ...
    1452              */
    1453             bool fPendingClose = false;
    1454             if (uFlags & INPUT_FLAG_EOF)
    1455             {
    1456                 fPendingClose = true;
    1457                 VBoxServiceVerbose(4, "ControlExec: Got last input block (PID %u) ...\n", uPID);
    1458             }
    1459 
    1460             uint32_t cbWritten;
    1461             if (VBoxServicePipeBufIsEnabled(&pData->stdIn))
    1462             {
    1463                 /*
    1464                  * Feed the data to the pipe.
    1465                  */
    1466                 rc = VBoxServicePipeBufWriteToBuf(&pData->stdIn, pabBuffer,
    1467                                                   cbSize, fPendingClose, &cbWritten);
    1468         #ifdef DEBUG
    1469                 VBoxServiceVerbose(4, "ControlExec: Written to StdIn buffer (PID %u): rc=%Rrc, uFlags=0x%x, cbAlloc=%u, cbSize=%u, cbOffset=%u\n",
    1470                                    uPID, rc, uFlags,
    1471                                    pData->stdIn.cbAllocated, pData->stdIn.cbSize, pData->stdIn.cbOffset);
    1472         #endif
    1473             }
    1474             else
    1475             {
    1476                 /* If input buffer is not enabled anymore we cannot handle that data ... */
    1477                 rc = VERR_BAD_PIPE;
    1478             }
    1479 
    1480             uint32_t uStatus = INPUT_STS_UNDEFINED;
    1481             if (RT_SUCCESS(rc))
    1482             {
    1483                 if (cbWritten || !cbSize) /* Did we write something or was there anything to write at all? */
    1484                 {
    1485                     uStatus = INPUT_STS_WRITTEN;
    1486                     uFlags = 0;
    1487                 }
    1488             }
    1489             else
    1490             {
    1491                 if (rc == VERR_BAD_PIPE)
    1492                     uStatus = INPUT_STS_TERMINATED;
    1493                 else if (rc == VERR_BUFFER_OVERFLOW)
    1494                     uStatus = INPUT_STS_OVERFLOW;
    1495                 else
    1496                 {
    1497                     uStatus = INPUT_STS_ERROR;
    1498                     uFlags = rc;
    1499                 }
    1500             }
    1501 
    1502             if (uStatus > INPUT_STS_UNDEFINED)
    1503             {
    1504                 VBoxServiceVerbose(3, "ControlExec: VbglR3GuestCtrlExecReportStatusIn (PID %u), Status = %u, Flags=%u, cbWritten=%u\n",
    1505                                    uPID, uStatus, uFlags, cbWritten);
    1506 
    1507                 /* Note: Since the context ID is unique the request *has* to be completed here,
    1508                  *       regardless whether we got data or not! Otherwise the progress object
    1509                  *       on the host never will get completed! */
    1510                 rc = VbglR3GuestCtrlExecReportStatusIn(u32ClientId, uContextID, uPID,
    1511                                                        uStatus, uFlags, (uint32_t)cbWritten);
     1260        bool fPendingClose = false;
     1261        if (uFlags & INPUT_FLAG_EOF)
     1262        {
     1263            fPendingClose = true;
     1264            VBoxServiceVerbose(4, "ControlExec: Got last input block (PID %u) of size %u ...\n", uPID, cbSize);
     1265        }
     1266
     1267        rc = VBoxServiceControlExecThreadSetInput(uPID, fPendingClose, pabBuffer,
     1268                                                  cbSize, &cbWritten);
     1269        VBoxServiceVerbose(4, "ControlExec: Written input (PID %u): rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n",
     1270                           uPID, rc, uFlags, fPendingClose, cbSize, cbWritten);
     1271        if (RT_SUCCESS(rc))
     1272        {
     1273            if (cbWritten || !cbSize) /* Did we write something or was there anything to write at all? */
     1274            {
     1275                uStatus = INPUT_STS_WRITTEN;
     1276                uFlags = 0;
    15121277            }
    15131278        }
    15141279        else
    1515             rc = VERR_NOT_FOUND; /* PID not found! */
     1280        {
     1281            if (rc == VERR_BAD_PIPE)
     1282                uStatus = INPUT_STS_TERMINATED;
     1283            else if (rc == VERR_BUFFER_OVERFLOW)
     1284                uStatus = INPUT_STS_OVERFLOW;
     1285        }
    15161286    }
    15171287    RTMemFree(pabBuffer);
     1288
     1289    /*
     1290     * If there was an error and we did not set the host status
     1291     * yet, then do it now.
     1292     */
     1293    if (   RT_FAILURE(rc)
     1294        && uStatus == INPUT_STS_UNDEFINED)
     1295    {
     1296        uStatus = INPUT_STS_ERROR;
     1297        uFlags = rc;
     1298    }
     1299    Assert(uStatus > INPUT_STS_UNDEFINED);
     1300
     1301    VBoxServiceVerbose(3, "ControlExec: Input processed (PID %u), Status=%u, Flags=0x%x, cbWritten=%u\n",
     1302                       uPID, uStatus, uFlags, cbWritten);
     1303
     1304    /* Note: Since the context ID is unique the request *has* to be completed here,
     1305     *       regardless whether we got data or not! Otherwise the progress object
     1306     *       on the host never will get completed! */
     1307    rc = VbglR3GuestCtrlExecReportStatusIn(u32ClientId, uContextID, uPID,
     1308                                           uStatus, uFlags, (uint32_t)cbWritten);
     1309
    15181310    VBoxServiceVerbose(3, "ControlExec: VBoxServiceControlExecHandleCmdSetInput returned with %Rrc\n", rc);
    15191311    return rc;
     
    15401332    if (RT_SUCCESS(rc))
    15411333    {
    1542         PVBOXSERVICECTRLTHREAD pNode = VBoxServiceControlExecFindProcess(uPID);
    1543         if (pNode)
    1544         {
    1545             PVBOXSERVICECTRLTHREADDATAEXEC pData = (PVBOXSERVICECTRLTHREADDATAEXEC)pNode->pvData;
    1546             AssertPtr(pData);
    1547 
    1548             const uint32_t cbSize = _1M;
    1549             uint32_t cbRead = cbSize;
    1550             uint8_t *pBuf = (uint8_t*)RTMemAlloc(cbSize);
    1551             if (pBuf)
    1552             {
    1553                 /* If the stdout pipe buffer is enabled (that is, still could be filled by a running
    1554                  * process) wait for the signal to arrive so that we don't return without any actual
    1555                  * data read. */
    1556                 if (VBoxServicePipeBufIsEnabled(&pData->stdOut))
    1557                 {
    1558                     VBoxServiceVerbose(4, "ControlExec: Waiting for output data becoming ready ...\n");
    1559                     /** @todo Add a timeout here!  */
    1560                     rc = VBoxServicePipeBufWaitForEvent(&pData->stdOut, RT_INDEFINITE_WAIT);
    1561                 }
    1562                 if (RT_SUCCESS(rc))
    1563                 {
    1564                     /** @todo Use uHandleID to distinguish between stdout/stderr! */
    1565                     rc = VBoxServicePipeBufRead(&pData->stdOut, pBuf, cbSize, &cbRead);
    1566                     if (RT_SUCCESS(rc))
    1567                     {
    1568                         /* Note: Since the context ID is unique the request *has* to be completed here,
    1569                          *       regardless whether we got data or not! Otherwise the progress object
    1570                          *       on the host never will get completed! */
    1571                         /* cbRead now contains actual size. */
    1572                         rc = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, 0 /* Handle ID */, 0 /* Flags */,
    1573                                                         pBuf, cbRead);
    1574                     }
    1575                 }
    1576                 RTMemFree(pBuf);
    1577             }
    1578             else
    1579                 rc = VERR_NO_MEMORY;
     1334        uint32_t cbRead;
     1335        uint8_t *pBuf = (uint8_t*)RTMemAlloc(_64K);
     1336        if (pBuf)
     1337        {
     1338            rc = VBoxServiceControlExecThreadGetOutput(uPID, uHandleID, RT_INDEFINITE_WAIT /* Timeout */,
     1339                                                       pBuf, _64K /* cbSize */, &cbRead);
     1340            if (RT_SUCCESS(rc))
     1341            {
     1342                /* Note: Since the context ID is unique the request *has* to be completed here,
     1343                 *       regardless whether we got data or not! Otherwise the progress object
     1344                 *       on the host never will get completed! */
     1345                /* cbRead now contains actual size. */
     1346                rc = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, uHandleID, 0 /* Flags */,
     1347                                                pBuf, cbRead);
     1348            }
     1349            RTMemFree(pBuf);
    15801350        }
    15811351        else
    1582             rc = VERR_NOT_FOUND; /* PID not found! */
     1352            rc = VERR_NO_MEMORY;
    15831353    }
    15841354    else
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r36338 r36548  
    307307                                                  const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
    308308                                                  const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS);
    309 extern void         VBoxServiceControlExecDestroyThreadData(PVBOXSERVICECTRLTHREADDATAEXEC pThread);
     309extern void         VBoxServiceControlExecThreadDestroy(PVBOXSERVICECTRLTHREADDATAEXEC pThread);
    310310#endif /* VBOX_WITH_GUEST_CONTROL */
    311311
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

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