VirtualBox

Changeset 36305 in vbox


Ignore:
Timestamp:
Mar 17, 2011 1:46:21 PM (14 years ago)
Author:
vboxsync
Message:

VBoxService/GuestExec: Fixed file copy on Linux, refactored pipe buffer into own module.

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

Legend:

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

    r35385 r36305  
    6969 VBoxService_SOURCES    += \
    7070        VBoxServiceControl.cpp \
    71         VBoxServiceControlExec.cpp
     71        VBoxServiceControlExec.cpp \
     72        VBoxServicePipeBuf.cpp
    7273endif
    7374
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp

    r36206 r36305  
    3434#include <iprt/process.h>
    3535#include <iprt/string.h>
    36 #include <iprt/semaphore.h>
    3736#include <iprt/stream.h>
    3837#include <iprt/thread.h>
     
    4039#include <VBox/VBoxGuestLib.h>
    4140#include <VBox/HostServices/GuestControlSvc.h>
     41
    4242#include "VBoxServiceInternal.h"
    4343#include "VBoxServiceUtils.h"
     44#include "VBoxServicePipeBuf.h"
    4445
    4546using namespace guestControl;
    4647
    4748extern RTLISTNODE g_GuestControlExecThreads;
    48 
    49 static int VBoxServiceControlExecPipeInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe);
    50 static int VBoxServiceControlExecPipeBufRead(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
    51                                              uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead);
    52 static int VBoxServiceControlExecPipeBufWrite(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
    53                                               uint8_t *pbData, uint32_t cbData, bool fPendingClose, uint32_t *pcbWritten);
    54 static bool VBoxServiceControlExecPipeBufIsEnabled(PVBOXSERVICECTRLEXECPIPEBUF pBuf);
    55 static int VBoxServiceControlExecPipeBufSetStatus(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fEnabled);
    56 static void VBoxServiceControlExecPipeBufDestroy(PVBOXSERVICECTRLEXECPIPEBUF pBuf);
    5749
    5850
     
    6961                                                           PVBOXSERVICECTRLEXECPIPEBUF pStdInBuf)
    7062{
    71     int rc = RTCritSectEnter(&pStdInBuf->CritSect);
    72     if (RT_SUCCESS(rc))
    73     {
    74         int rc2 = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_WRITABLE);
    75         /* Don't assert if writable handle is not in poll set anymore. */
    76         if (   RT_FAILURE(rc2)
    77             && rc2 != VERR_POLL_HANDLE_ID_NOT_FOUND)
    78                 {
    79             AssertRC(rc2);
    80                 }
    81 
    82         rc2 = RTPipeClose(*phStdInW);
    83         AssertRC(rc2);
    84         *phStdInW = NIL_RTPIPE;
    85 
    86         /* Mark the stdin buffer as dead; we're not using it anymore. */
    87         pStdInBuf->fEnabled = false;
    88 
    89         rc2 = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_ERROR);
    90         AssertRC(rc2);
    91 
    92         rc2 = RTCritSectLeave(&pStdInBuf->CritSect);
    93         if (RT_SUCCESS(rc))
    94             rc = rc2;
    95     }
     63    int rc = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_WRITABLE);
     64    /* Don't assert if writable handle is not in poll set anymore. */
     65    if (   RT_FAILURE(rc)
     66        && rc != VERR_POLL_HANDLE_ID_NOT_FOUND)
     67    {
     68        AssertRC(rc);
     69    }
     70
     71    /* Close writable stdin pipe. */
     72    rc = RTPipeClose(*phStdInW);
     73    AssertRC(rc);
     74    *phStdInW = NIL_RTPIPE;
     75
     76    /* Mark the stdin buffer as dead; we're not using it anymore. */
     77    rc = VBoxServicePipeBufSetStatus(pStdInBuf, false /* Disabled */);
     78    AssertRC(rc);
     79
     80    /* Remove stdin error handle from set. */
     81    rc = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_ERROR);
     82    AssertRC(rc);
     83
    9684    return rc;
    9785}
     
    112100                                                size_t *pcbWritten, bool *pfClose)
    113101{
     102    AssertPtrReturn(pStdInBuf, VERR_INVALID_PARAMETER);
    114103    AssertPtrReturn(pcbWritten, VERR_INVALID_PARAMETER);
    115104    AssertPtrReturn(pfClose, VERR_INVALID_PARAMETER);
    116105
    117     int rc = RTCritSectEnter(&pStdInBuf->CritSect);
    118     if (RT_SUCCESS(rc))
    119     {
    120         Assert(pStdInBuf->cbSize >= pStdInBuf->cbOffset);
    121         size_t cbToWrite = pStdInBuf->cbSize - pStdInBuf->cbOffset;
    122         cbToWrite = RT_MIN(cbToWrite, _1M);
    123         *pfClose = false;
    124         if (   pStdInBuf->fEnabled
    125             && cbToWrite)
    126         {
    127             rc = RTPipeWrite(hStdInW, &pStdInBuf->pbData[pStdInBuf->cbOffset], cbToWrite, pcbWritten);
    128             if (RT_SUCCESS(rc))
    129             {
    130                 pStdInBuf->fNeedNotification = true;
    131                 if (rc != VINF_TRY_AGAIN)
    132                     pStdInBuf->cbOffset += *pcbWritten;
    133 
    134                 /* Did somebody tell us that we should come to an end,
    135                  * e.g. no more data coming in? */
    136                 if (pStdInBuf->fPendingClose)
    137                 {
    138                     /* When we wrote out all data in the buffer we
    139                      * can finally shutdown. */
    140                     if (pStdInBuf->cbSize == pStdInBuf->cbOffset)
    141                     {
    142                         *pfClose = true;
    143                     }
    144                     else if (pStdInBuf->fNeedNotification)
    145                     {
    146                         /* Still data to push out - so we need another
    147                          * poll round! Write something into the notification pipe. */
    148                         size_t cbWrittenIgnore;
    149                         int rc2 = RTPipeWrite(pStdInBuf->hNotificationPipeW, "i", 1, &cbWrittenIgnore);
    150 
    151                         /* Disable notification until it is set again on successful write. */
    152                         pStdInBuf->fNeedNotification = !RT_SUCCESS(rc2);
    153                     }
    154                 }
    155             }
    156             else
    157             {
    158                 *pcbWritten = 0;
    159                 pStdInBuf->fEnabled = pStdInBuf->fEnabled;
    160             }
    161 #ifdef DEBUG
    162             VBoxServiceVerbose(1, "ControlExec: Written StdIn: cbOffset=%u, pcbWritten=%u,  rc=%Rrc, cbAlloc=%u, cbSize=%u\n",
    163                                pStdInBuf->cbOffset, *pcbWritten, rc,
    164                                pStdInBuf->cbAllocated, pStdInBuf->cbSize);
    165 #endif
    166         }
    167         else
    168         {
    169             *pcbWritten = 0;
    170             pStdInBuf->fNeedNotification = pStdInBuf->fEnabled;
    171         }
    172 
    173         if (   !*pcbWritten
    174             && pStdInBuf->fEnabled)
    175         {
    176             /*
    177              * Nothing else left to write now? Remove the writable event from the poll set
    178              * to not trigger too high CPU loads.
    179              */
    180             rc = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_WRITABLE);
    181             AssertRC(rc);
    182         }
    183 
    184         int rc2 = RTCritSectLeave(&pStdInBuf->CritSect);
    185         if (RT_SUCCESS(rc))
    186             rc = rc2;
    187     }
     106    size_t cbLeft;
     107    int rc = VBoxServicePipeBufWriteToPipe(pStdInBuf, hStdInW, pcbWritten, &cbLeft);
     108
     109    /* If we have written all data which is in the buffer set the close flag. */
     110    *pfClose = (cbLeft == 0) && VBoxServicePipeBufIsClosing(pStdInBuf);
     111
     112    if (   !*pcbWritten
     113        && VBoxServicePipeBufIsEnabled(pStdInBuf))
     114    {
     115        /*
     116         * Nothing else left to write now? Remove the writable event from the poll set
     117         * to not trigger too high CPU loads.
     118         */
     119        int rc2 = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_WRITABLE);
     120        AssertRC(rc2);
     121    }
     122
     123    VBoxServiceVerbose(3, "VBoxServiceControlExecProcWriteStdIn: Written=%u, Left=%u, rc=%Rrc\n",
     124                       *pcbWritten, cbLeft, rc);
    188125    return rc;
    189126}
     
    212149                                                  pStdInBuf, *phStdInW,
    213150                                                  pcbWritten, &fClose);
    214         if (rc == VINF_TRY_AGAIN)
     151        if (   rc == VINF_TRY_AGAIN
     152            || rc == VERR_MORE_DATA)
    215153            rc = VINF_SUCCESS;
    216154        if (RT_FAILURE(rc))
     
    293231    if (RT_SUCCESS(rc2) && cbRead)
    294232    {
    295 #if 0
    296         /* Only used for "real-time" stdout/stderr data; gets sent immediately (later)! */
    297         rc = VbglR3GuestCtrlExecSendOut(pThread->uClientID, pThread->uContextID,
    298                                         pData->uPID, uHandleId, 0 /* u32Flags */,
    299                                         abBuf, cbRead);
    300         if (RT_FAILURE(rc))
    301         {
    302             VBoxServiceError("ControlExec: Error while sending real-time output data, rc=%Rrc, cbRead=%u, CID=%u, PID=%u\n",
    303                              rc, cbRead, pThread->uClientID, pData->uPID);
    304         }
    305         else
    306         {
    307 #endif
    308             uint32_t cbWritten;
    309             rc = VBoxServiceControlExecPipeBufWrite(pStdOutBuf, abBuf,
    310                                                     cbRead, false /* Pending close */, &cbWritten);
    311             if (RT_SUCCESS(rc))
    312             {
    313                 Assert(cbRead == cbWritten);
    314                 /* Make sure we go another poll round in case there was too much data
    315                    for the buffer to hold. */
    316                 fPollEvt &= RTPOLL_EVT_ERROR;
    317             }
    318 #if 0
    319         }
    320 #endif
     233        uint32_t cbWritten;
     234        rc = VBoxServicePipeBufWriteToBuf(pStdOutBuf, abBuf,
     235                                          cbRead, false /* Pending close */, &cbWritten);
     236        if (RT_SUCCESS(rc))
     237        {
     238            Assert(cbRead == cbWritten);
     239            /* Make sure we go another poll round in case there was too much data
     240               for the buffer to hold. */
     241            fPollEvt &= RTPOLL_EVT_ERROR;
     242        }
    321243    }
    322244    else if (RT_FAILURE(rc2))
     
    590512    if (RT_SUCCESS(rc))
    591513    {
    592         VBoxServiceControlExecPipeBufSetStatus(&pData->stdIn, false /* Disabled */);
    593         VBoxServiceControlExecPipeBufSetStatus(&pData->stdOut, false /* Disabled */);
    594         VBoxServiceControlExecPipeBufSetStatus(&pData->stdErr, false /* Disabled */);
     514        VBoxServicePipeBufSetStatus(&pData->stdIn, false /* Disabled */);
     515        VBoxServicePipeBufSetStatus(&pData->stdOut, false /* Disabled */);
     516        VBoxServicePipeBufSetStatus(&pData->stdErr, false /* Disabled */);
    595517
    596518        /* Since the process is not alive anymore, destroy its local
    597519         * stdin pipe buffer - it's not used anymore and can eat up quite
    598520         * a bit of memory. */
    599         VBoxServiceControlExecPipeBufDestroy(&pData->stdIn);
     521        VBoxServicePipeBufDestroy(&pData->stdIn);
    600522
    601523        uint32_t uStatus = PROC_STS_UNDEFINED;
     
    628550        else if (ProcessStatus.enmReason == RTPROCEXITREASON_NORMAL)
    629551        {
    630             VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_NORMAL\n");
     552            VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_NORMAL (%u)\n",
     553                               ProcessStatus.iStatus);
    631554
    632555            uStatus = PROC_STS_TEN;
     
    635558        else if (ProcessStatus.enmReason == RTPROCEXITREASON_SIGNAL)
    636559        {
    637             VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_SIGNAL\n");
     560            VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_SIGNAL (%u)\n",
     561                               ProcessStatus.iStatus);
    638562
    639563            uStatus = PROC_STS_TES;
     
    642566        else if (ProcessStatus.enmReason == RTPROCEXITREASON_ABEND)
    643567        {
    644             VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_ABEND\n");
     568            VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_ABEND (%u)\n",
     569                               ProcessStatus.iStatus);
    645570
    646571            uStatus = PROC_STS_TEA;
     
    712637
    713638    return rc;
    714 }
    715 
    716 
    717 /**
    718  * Initializes a pipe buffer.
    719  *
    720  * @returns IPRT status code.
    721  * @param   pBuf                    The pipe buffer to initialize.
    722  * @param   fNeedNotificationPipe   Whether the buffer needs a notification
    723  *                                  pipe or not.
    724  */
    725 static int VBoxServiceControlExecPipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe)
    726 {
    727     AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER);
    728 
    729     /** @todo Add allocation size as function parameter! */
    730     pBuf->pbData = (uint8_t *)RTMemAlloc(_64K); /* Start with a 64k buffer. */
    731     AssertReturn(pBuf->pbData, VERR_NO_MEMORY);
    732     pBuf->cbAllocated = _64K;
    733     pBuf->cbSize = 0;
    734     pBuf->cbOffset = 0;
    735     pBuf->fEnabled = true;
    736     pBuf->fPendingClose = false;
    737     pBuf->fNeedNotification = fNeedNotificationPipe;
    738     pBuf->hNotificationPipeW = NIL_RTPIPE;
    739     pBuf->hNotificationPipeR = NIL_RTPIPE;
    740     pBuf->hEventSem = NIL_RTSEMEVENT;
    741 
    742     int rc = RTSemEventCreate(&pBuf->hEventSem);
    743     if (RT_SUCCESS(rc))
    744     {
    745         rc = RTCritSectInit(&pBuf->CritSect);
    746         if (RT_SUCCESS(rc) && fNeedNotificationPipe)
    747         {
    748             rc = RTPipeCreate(&pBuf->hNotificationPipeR, &pBuf->hNotificationPipeW, 0);
    749             if (RT_FAILURE(rc))
    750                 RTCritSectDelete(&pBuf->CritSect);
    751         }
    752     }
    753     return rc;
    754 }
    755 
    756 
    757 /**
    758  * Reads out data from a specififed pipe buffer.
    759  *
    760  * @return  IPRT status code.
    761  * @param   pBuf                        Pointer to pipe buffer to read the data from.
    762  * @param   pbBuffer                    Pointer to buffer to store the read out data.
    763  * @param   cbBuffer                    Size (in bytes) of the buffer where to store the data.
    764  * @param   pcbToRead                   Pointer to desired amount (in bytes) of data to read,
    765  *                                      will reflect the actual amount read on return.
    766  */
    767 static int VBoxServiceControlExecPipeBufRead(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
    768                                              uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead)
    769 {
    770     AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER);
    771     AssertPtrReturn(pbBuffer, VERR_INVALID_PARAMETER);
    772     AssertReturn(cbBuffer, VERR_INVALID_PARAMETER);
    773     AssertPtrReturn(pcbToRead, VERR_INVALID_PARAMETER);
    774 
    775     int rc = RTCritSectEnter(&pBuf->CritSect);
    776     if (RT_SUCCESS(rc))
    777     {
    778         Assert(pBuf->cbSize >= pBuf->cbOffset);
    779         if (*pcbToRead > pBuf->cbSize - pBuf->cbOffset)
    780             *pcbToRead = pBuf->cbSize - pBuf->cbOffset;
    781 
    782         if (*pcbToRead > cbBuffer)
    783             *pcbToRead = cbBuffer;
    784 
    785         if (*pcbToRead > 0)
    786         {
    787             memcpy(pbBuffer, pBuf->pbData + pBuf->cbOffset, *pcbToRead);
    788             pBuf->cbOffset += *pcbToRead;
    789 
    790             RTSemEventSignal(pBuf->hEventSem);
    791         }
    792         else
    793         {
    794             pbBuffer = NULL;
    795             *pcbToRead = 0;
    796         }
    797         rc = RTCritSectLeave(&pBuf->CritSect);
    798     }
    799     return rc;
    800 }
    801 
    802 
    803 /**
    804  * Writes data into a specififed pipe buffer.
    805  *
    806  * @return  IPRT status code.
    807  * @param   pBuf                        Pointer to pipe buffer to write data into.
    808  * @param   pbData                      Pointer to byte data to write.
    809  * @param   cbData                      Data size (in bytes) to write.
    810  * @param   fPendingClose               Needs the pipe (buffer) to be closed next time we have the chance to?
    811  * @param   pcbWritten                  Pointer to where the amount of written bytes get stored. Optional.
    812  */
    813 static int VBoxServiceControlExecPipeBufWrite(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
    814                                               uint8_t *pbData, uint32_t cbData, bool fPendingClose,
    815                                               uint32_t *pcbWritten)
    816 {
    817     AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER);
    818     AssertPtrReturn(pbData, VERR_INVALID_PARAMETER);
    819 
    820     int rc;
    821     if (pBuf->fEnabled)
    822     {
    823         rc = RTCritSectEnter(&pBuf->CritSect);
    824         if (RT_SUCCESS(rc))
    825         {
    826             /* Rewind the buffer if it's empty. */
    827             size_t     cbInBuf   = pBuf->cbSize - pBuf->cbOffset;
    828             bool const fAddToSet = cbInBuf == 0;
    829             if (fAddToSet)
    830                 pBuf->cbSize = pBuf->cbOffset = 0;
    831 
    832             /* Try and see if we can simply append the data. */
    833             if (cbData + pBuf->cbSize <= pBuf->cbAllocated)
    834             {
    835                 memcpy(&pBuf->pbData[pBuf->cbSize], pbData, cbData);
    836                 pBuf->cbSize += cbData;
    837             }
    838             else
    839             {
    840                 /* Move any buffered data to the front. */
    841                 cbInBuf = pBuf->cbSize - pBuf->cbOffset;
    842                 if (cbInBuf == 0)
    843                     pBuf->cbSize = pBuf->cbOffset = 0;
    844                 else if (pBuf->cbOffset) /* Do we have something to move? */
    845                 {
    846                     memmove(pBuf->pbData, &pBuf->pbData[pBuf->cbOffset], cbInBuf);
    847                     pBuf->cbSize = cbInBuf;
    848                     pBuf->cbOffset = 0;
    849                 }
    850 
    851                 /* Do we need to grow the buffer? */
    852                 if (cbData + pBuf->cbSize > pBuf->cbAllocated)
    853                 {
    854                     size_t cbAlloc = pBuf->cbSize + cbData;
    855                     cbAlloc = RT_ALIGN_Z(cbAlloc, _64K);
    856                     void *pvNew = RTMemRealloc(pBuf->pbData, cbAlloc);
    857                     if (pvNew)
    858                     {
    859                         pBuf->pbData = (uint8_t *)pvNew;
    860                         pBuf->cbAllocated = cbAlloc;
    861                     }
    862                     else
    863                         rc = VERR_NO_MEMORY;
    864                 }
    865 
    866                 /* Finally, copy the data. */
    867                 if (RT_SUCCESS(rc))
    868                 {
    869                     if (cbData + pBuf->cbSize <= pBuf->cbAllocated)
    870                     {
    871                         memcpy(&pBuf->pbData[pBuf->cbSize], pbData, cbData);
    872                         pBuf->cbSize += cbData;
    873                     }
    874                     else
    875                         rc = VERR_BUFFER_OVERFLOW;
    876                 }
    877             }
    878 
    879             if (RT_SUCCESS(rc))
    880             {
    881                 /*
    882                  * Was this the final read/write to do on this buffer? Then close it
    883                  * next time we have the chance to.
    884                  */
    885                 if (fPendingClose)
    886                     pBuf->fPendingClose = fPendingClose;
    887 
    888                 /*
    889                  * Wake up the thread servicing the process so it can feed it
    890                  * (if we have a notification helper pipe).
    891                  */
    892                 if (pBuf->fNeedNotification)
    893                 {
    894                     size_t cbWritten;
    895                     int rc2 = RTPipeWrite(pBuf->hNotificationPipeW, "i", 1, &cbWritten);
    896 
    897                     /* Disable notification until it is set again on successful write. */
    898                     pBuf->fNeedNotification = !RT_SUCCESS(rc2);
    899                 }
    900 
    901                 /* Report back written bytes (if wanted). */
    902                 if (pcbWritten)
    903                     *pcbWritten = cbData;
    904 
    905                 RTSemEventSignal(pBuf->hEventSem);
    906             }
    907             int rc2 = RTCritSectLeave(&pBuf->CritSect);
    908             if (RT_SUCCESS(rc))
    909                 rc = rc2;
    910         }
    911     }
    912     else
    913         rc = VERR_BAD_PIPE;
    914     return rc;
    915 }
    916 
    917 
    918 /**
    919  * Returns whether a pipe buffer is active or not.
    920  *
    921  * @return  bool            True if pipe buffer is active, false if not.
    922  * @param   pBuf            The pipe buffer.
    923  */
    924 static bool VBoxServiceControlExecPipeBufIsEnabled(PVBOXSERVICECTRLEXECPIPEBUF pBuf)
    925 {
    926     AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER);
    927 
    928     bool fEnabled = false;
    929     if (RT_SUCCESS(RTCritSectEnter(&pBuf->CritSect)))
    930     {
    931         fEnabled = pBuf->fEnabled;
    932         RTCritSectLeave(&pBuf->CritSect);
    933     }
    934     return fEnabled;
    935 }
    936 
    937 
    938 /**
    939  * Sets the current status (enabled/disabled) of a pipe buffer.
    940  *
    941  * @return  IPRT status code.
    942  * @param   pBuf            The pipe buffer.
    943  * @param   fEnabled        Pipe buffer status to set.
    944  */
    945 static int VBoxServiceControlExecPipeBufSetStatus(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fEnabled)
    946 {
    947     AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER);
    948 
    949     int rc = RTCritSectEnter(&pBuf->CritSect);
    950     if (RT_SUCCESS(rc))
    951     {
    952         pBuf->fEnabled = fEnabled;
    953         /* Let waiter know that something has changed ... */
    954         if (pBuf->hEventSem)
    955             RTSemEventSignal(pBuf->hEventSem);
    956         rc = RTCritSectLeave(&pBuf->CritSect);
    957     }
    958     return rc;
    959 }
    960 
    961 
    962 /**
    963  * Deletes a pipe buffer.
    964  * Note: Not thread safe -- only call this when nobody is relying on the
    965  *       data anymore!
    966  *
    967  * @param   pBuf            The pipe buffer.
    968  */
    969 static void VBoxServiceControlExecPipeBufDestroy(PVBOXSERVICECTRLEXECPIPEBUF pBuf)
    970 {
    971     AssertPtr(pBuf);
    972     if (pBuf->pbData)
    973     {
    974         RTMemFree(pBuf->pbData);
    975         pBuf->pbData = NULL;
    976         pBuf->cbAllocated = 0;
    977         pBuf->cbSize = 0;
    978         pBuf->cbOffset = 0;
    979     }
    980 
    981     RTPipeClose(pBuf->hNotificationPipeR);
    982     pBuf->hNotificationPipeR = NIL_RTPIPE;
    983     RTPipeClose(pBuf->hNotificationPipeW);
    984     pBuf->hNotificationPipeW = NIL_RTPIPE;
    985 
    986     RTSemEventDestroy(pBuf->hEventSem);
    987     RTCritSectDelete(&pBuf->CritSect);
    988639}
    989640
     
    1086737
    1087738        /* Init buffers. */
    1088         rc = VBoxServiceControlExecPipeBufInit(&pData->stdOut, false /*fNeedNotificationPipe*/);
     739        rc = VBoxServicePipeBufInit(&pData->stdOut, false /*fNeedNotificationPipe*/);
    1089740        if (RT_SUCCESS(rc))
    1090741        {
    1091             rc = VBoxServiceControlExecPipeBufInit(&pData->stdErr, false /*fNeedNotificationPipe*/);
     742            rc = VBoxServicePipeBufInit(&pData->stdErr, false /*fNeedNotificationPipe*/);
    1092743            if (RT_SUCCESS(rc))
    1093                 rc = VBoxServiceControlExecPipeBufInit(&pData->stdIn, true /*fNeedNotificationPipe*/);
     744                rc = VBoxServicePipeBufInit(&pData->stdIn, true /*fNeedNotificationPipe*/);
    1094745        }
    1095746    }
     
    1128779        RTStrFree(pData->pszPassword);
    1129780
    1130         VBoxServiceControlExecPipeBufDestroy(&pData->stdOut);
    1131         VBoxServiceControlExecPipeBufDestroy(&pData->stdErr);
    1132         VBoxServiceControlExecPipeBufDestroy(&pData->stdIn);
     781        VBoxServicePipeBufDestroy(&pData->stdOut);
     782        VBoxServicePipeBufDestroy(&pData->stdErr);
     783        VBoxServicePipeBufDestroy(&pData->stdIn);
    1133784
    1134785        RTMemFree(pData);
     
    13761027            if (*pszAsUser)
    13771028                uProcFlags |= RTPROC_FLAGS_SERVICE;
    1378 
     1029#ifdef DEBUG
     1030            char *pszCmdLine;
     1031            rc = RTGetOptArgvToString(&pszCmdLine, papszArgsExp, 0 /* Default */);
     1032            AssertRC(rc);
     1033            VBoxServiceVerbose(3, "ControlExec: Executing: %s %s\n",
     1034                               szExecExp, pszCmdLine);
     1035            RTStrFree(pszCmdLine);
     1036#endif
    13791037            /* Do normal execution. */
    13801038            rc = RTProcCreateEx(szExecExp, papszArgsExp, hEnv, uProcFlags,
     
    14741132                                                                         pData->pszUser, pData->pszPassword,
    14751133                                                                         &hProcess);
    1476 
     1134                                if (RT_FAILURE(rc))
     1135                                    VBoxServiceError("ControlExec: Error starting process, rc=%Rrc\n", rc);
    14771136                                /*
    14781137                                 * Tell the control thread that it can continue
     
    17991458            }
    18001459
    1801             /*
    1802              * Feed the data to the pipe.
    1803              */
    18041460            uint32_t cbWritten;
    1805             rc = VBoxServiceControlExecPipeBufWrite(&pData->stdIn, pabBuffer,
    1806                                                     cbSize, fPendingClose, &cbWritten);
    1807 #ifdef DEBUG
    1808             VBoxServiceVerbose(4, "ControlExec: Written to StdIn buffer (PID %u): rc=%Rrc, uFlags=0x%x, cbAlloc=%u, cbSize=%u, cbOffset=%u\n",
    1809                                uPID, rc, uFlags,
    1810                                pData->stdIn.cbAllocated, pData->stdIn.cbSize, pData->stdIn.cbOffset);
    1811 #endif
     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
    18121480            uint32_t uStatus = INPUT_STS_UNDEFINED;
    18131481            if (RT_SUCCESS(rc))
     
    18341502            if (uStatus > INPUT_STS_UNDEFINED)
    18351503            {
     1504                VBoxServiceVerbose(3, "ControlExec: VbglR3GuestCtrlExecReportStatusIn (PID %u), Status = %u, Flags=%u, cbWritten=%u\n",
     1505                                   uPID, uStatus, uFlags, cbWritten);
     1506
    18361507                /* Note: Since the context ID is unique the request *has* to be completed here,
    18371508                 *       regardless whether we got data or not! Otherwise the progress object
     
    18831554                 * process) wait for the signal to arrive so that we don't return without any actual
    18841555                 * data read. */
    1885                 if (VBoxServiceControlExecPipeBufIsEnabled(&pData->stdOut))
     1556                if (VBoxServicePipeBufIsEnabled(&pData->stdOut))
    18861557                {
    18871558                    VBoxServiceVerbose(4, "ControlExec: Waiting for output data becoming ready ...\n");
    1888                     rc = RTSemEventWait(pData->stdOut.hEventSem, RT_INDEFINITE_WAIT);
     1559                    /** @todo Add a timeout here!  */
     1560                    rc = VBoxServicePipeBufWaitForEvent(&pData->stdOut, RT_INDEFINITE_WAIT);
    18891561                }
    18901562                if (RT_SUCCESS(rc))
    18911563                {
    18921564                    /** @todo Use uHandleID to distinguish between stdout/stderr! */
    1893                     rc = VBoxServiceControlExecPipeBufRead(&pData->stdOut, pBuf, cbSize, &cbRead);
     1565                    rc = VBoxServicePipeBufRead(&pData->stdOut, pBuf, cbSize, &cbRead);
    18941566                    if (RT_SUCCESS(rc))
    18951567                    {
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp

    r35244 r36305  
    186186        {
    187187            rc = RTFileRead(hInput, abBuf, sizeof(abBuf), &cbRead);
    188             if (RT_SUCCESS(rc))
     188            if (RT_SUCCESS(rc) && cbRead > 0)
    189189            {
    190190                rc = RTFileWrite(hOutput, abBuf, cbRead, NULL /* Try to write all at once! */);
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