Changeset 36305 in vbox
- Timestamp:
- Mar 17, 2011 1:46:21 PM (14 years ago)
- 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 69 69 VBoxService_SOURCES += \ 70 70 VBoxServiceControl.cpp \ 71 VBoxServiceControlExec.cpp 71 VBoxServiceControlExec.cpp \ 72 VBoxServicePipeBuf.cpp 72 73 endif 73 74 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
r36206 r36305 34 34 #include <iprt/process.h> 35 35 #include <iprt/string.h> 36 #include <iprt/semaphore.h>37 36 #include <iprt/stream.h> 38 37 #include <iprt/thread.h> … … 40 39 #include <VBox/VBoxGuestLib.h> 41 40 #include <VBox/HostServices/GuestControlSvc.h> 41 42 42 #include "VBoxServiceInternal.h" 43 43 #include "VBoxServiceUtils.h" 44 #include "VBoxServicePipeBuf.h" 44 45 45 46 using namespace guestControl; 46 47 47 48 extern 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);57 49 58 50 … … 69 61 PVBOXSERVICECTRLEXECPIPEBUF pStdInBuf) 70 62 { 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 96 84 return rc; 97 85 } … … 112 100 size_t *pcbWritten, bool *pfClose) 113 101 { 102 AssertPtrReturn(pStdInBuf, VERR_INVALID_PARAMETER); 114 103 AssertPtrReturn(pcbWritten, VERR_INVALID_PARAMETER); 115 104 AssertPtrReturn(pfClose, VERR_INVALID_PARAMETER); 116 105 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); 188 125 return rc; 189 126 } … … 212 149 pStdInBuf, *phStdInW, 213 150 pcbWritten, &fClose); 214 if (rc == VINF_TRY_AGAIN) 151 if ( rc == VINF_TRY_AGAIN 152 || rc == VERR_MORE_DATA) 215 153 rc = VINF_SUCCESS; 216 154 if (RT_FAILURE(rc)) … … 293 231 if (RT_SUCCESS(rc2) && cbRead) 294 232 { 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 } 321 243 } 322 244 else if (RT_FAILURE(rc2)) … … 590 512 if (RT_SUCCESS(rc)) 591 513 { 592 VBoxService ControlExecPipeBufSetStatus(&pData->stdIn, false /* Disabled */);593 VBoxService ControlExecPipeBufSetStatus(&pData->stdOut, false /* Disabled */);594 VBoxService ControlExecPipeBufSetStatus(&pData->stdErr, false /* Disabled */);514 VBoxServicePipeBufSetStatus(&pData->stdIn, false /* Disabled */); 515 VBoxServicePipeBufSetStatus(&pData->stdOut, false /* Disabled */); 516 VBoxServicePipeBufSetStatus(&pData->stdErr, false /* Disabled */); 595 517 596 518 /* Since the process is not alive anymore, destroy its local 597 519 * stdin pipe buffer - it's not used anymore and can eat up quite 598 520 * a bit of memory. */ 599 VBoxService ControlExecPipeBufDestroy(&pData->stdIn);521 VBoxServicePipeBufDestroy(&pData->stdIn); 600 522 601 523 uint32_t uStatus = PROC_STS_UNDEFINED; … … 628 550 else if (ProcessStatus.enmReason == RTPROCEXITREASON_NORMAL) 629 551 { 630 VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_NORMAL\n"); 552 VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_NORMAL (%u)\n", 553 ProcessStatus.iStatus); 631 554 632 555 uStatus = PROC_STS_TEN; … … 635 558 else if (ProcessStatus.enmReason == RTPROCEXITREASON_SIGNAL) 636 559 { 637 VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_SIGNAL\n"); 560 VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_SIGNAL (%u)\n", 561 ProcessStatus.iStatus); 638 562 639 563 uStatus = PROC_STS_TES; … … 642 566 else if (ProcessStatus.enmReason == RTPROCEXITREASON_ABEND) 643 567 { 644 VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_ABEND\n"); 568 VBoxServiceVerbose(3, "ControlExec: Process ended with RTPROCEXITREASON_ABEND (%u)\n", 569 ProcessStatus.iStatus); 645 570 646 571 uStatus = PROC_STS_TEA; … … 712 637 713 638 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 notification723 * 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 else793 {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 else839 {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 else863 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 else875 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 it883 * 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 it890 * (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 else913 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 the965 * 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);988 639 } 989 640 … … 1086 737 1087 738 /* Init buffers. */ 1088 rc = VBoxService ControlExecPipeBufInit(&pData->stdOut, false /*fNeedNotificationPipe*/);739 rc = VBoxServicePipeBufInit(&pData->stdOut, false /*fNeedNotificationPipe*/); 1089 740 if (RT_SUCCESS(rc)) 1090 741 { 1091 rc = VBoxService ControlExecPipeBufInit(&pData->stdErr, false /*fNeedNotificationPipe*/);742 rc = VBoxServicePipeBufInit(&pData->stdErr, false /*fNeedNotificationPipe*/); 1092 743 if (RT_SUCCESS(rc)) 1093 rc = VBoxService ControlExecPipeBufInit(&pData->stdIn, true /*fNeedNotificationPipe*/);744 rc = VBoxServicePipeBufInit(&pData->stdIn, true /*fNeedNotificationPipe*/); 1094 745 } 1095 746 } … … 1128 779 RTStrFree(pData->pszPassword); 1129 780 1130 VBoxService ControlExecPipeBufDestroy(&pData->stdOut);1131 VBoxService ControlExecPipeBufDestroy(&pData->stdErr);1132 VBoxService ControlExecPipeBufDestroy(&pData->stdIn);781 VBoxServicePipeBufDestroy(&pData->stdOut); 782 VBoxServicePipeBufDestroy(&pData->stdErr); 783 VBoxServicePipeBufDestroy(&pData->stdIn); 1133 784 1134 785 RTMemFree(pData); … … 1376 1027 if (*pszAsUser) 1377 1028 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 1379 1037 /* Do normal execution. */ 1380 1038 rc = RTProcCreateEx(szExecExp, papszArgsExp, hEnv, uProcFlags, … … 1474 1132 pData->pszUser, pData->pszPassword, 1475 1133 &hProcess); 1476 1134 if (RT_FAILURE(rc)) 1135 VBoxServiceError("ControlExec: Error starting process, rc=%Rrc\n", rc); 1477 1136 /* 1478 1137 * Tell the control thread that it can continue … … 1799 1458 } 1800 1459 1801 /*1802 * Feed the data to the pipe.1803 */1804 1460 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 1812 1480 uint32_t uStatus = INPUT_STS_UNDEFINED; 1813 1481 if (RT_SUCCESS(rc)) … … 1834 1502 if (uStatus > INPUT_STS_UNDEFINED) 1835 1503 { 1504 VBoxServiceVerbose(3, "ControlExec: VbglR3GuestCtrlExecReportStatusIn (PID %u), Status = %u, Flags=%u, cbWritten=%u\n", 1505 uPID, uStatus, uFlags, cbWritten); 1506 1836 1507 /* Note: Since the context ID is unique the request *has* to be completed here, 1837 1508 * regardless whether we got data or not! Otherwise the progress object … … 1883 1554 * process) wait for the signal to arrive so that we don't return without any actual 1884 1555 * data read. */ 1885 if (VBoxService ControlExecPipeBufIsEnabled(&pData->stdOut))1556 if (VBoxServicePipeBufIsEnabled(&pData->stdOut)) 1886 1557 { 1887 1558 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); 1889 1561 } 1890 1562 if (RT_SUCCESS(rc)) 1891 1563 { 1892 1564 /** @todo Use uHandleID to distinguish between stdout/stderr! */ 1893 rc = VBoxService ControlExecPipeBufRead(&pData->stdOut, pBuf, cbSize, &cbRead);1565 rc = VBoxServicePipeBufRead(&pData->stdOut, pBuf, cbSize, &cbRead); 1894 1566 if (RT_SUCCESS(rc)) 1895 1567 { -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceToolBox.cpp
r35244 r36305 186 186 { 187 187 rc = RTFileRead(hInput, abBuf, sizeof(abBuf), &cbRead); 188 if (RT_SUCCESS(rc) )188 if (RT_SUCCESS(rc) && cbRead > 0) 189 189 { 190 190 rc = RTFileWrite(hOutput, abBuf, cbRead, NULL /* Try to write all at once! */);
Note:
See TracChangeset
for help on using the changeset viewer.