Changeset 35952 in vbox for trunk/src/VBox
- Timestamp:
- Feb 14, 2011 10:17:07 AM (14 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
r35692 r35952 76 76 77 77 /* Mark the stdin buffer as dead; we're not using it anymore. */ 78 pStdInBuf->f Alive= false;78 pStdInBuf->fEnabled = false; 79 79 80 80 rc2 = RTPollSetRemove(hPollSet, VBOXSERVICECTRLPIPEID_STDIN_ERROR); … … 113 113 cbToWrite = RT_MIN(cbToWrite, _1M); 114 114 *pfClose = false; 115 if ( pStdInBuf->f Alive115 if ( pStdInBuf->fEnabled 116 116 && cbToWrite) 117 117 { … … 148 148 { 149 149 *pcbWritten = 0; 150 pStdInBuf->f Alive = pStdInBuf->fAlive;150 pStdInBuf->fEnabled = pStdInBuf->fEnabled; 151 151 } 152 152 #ifdef DEBUG … … 159 159 { 160 160 *pcbWritten = 0; 161 pStdInBuf->fNeedNotification = pStdInBuf->f Alive;161 pStdInBuf->fNeedNotification = pStdInBuf->fEnabled; 162 162 } 163 163 164 164 if ( !*pcbWritten 165 && pStdInBuf->f Alive)165 && pStdInBuf->fEnabled) 166 166 { 167 167 /* … … 298 298 #endif 299 299 uint32_t cbWritten; 300 rc = VBoxServiceControlExec WritePipeBuffer(pStdOutBuf, abBuf,301 300 rc = VBoxServiceControlExecPipeBufWrite(pStdOutBuf, abBuf, 301 cbRead, false /* Pending close */, &cbWritten); 302 302 if (RT_SUCCESS(rc)) 303 303 { … … 581 581 if (RT_SUCCESS(rc)) 582 582 { 583 VBoxServiceControlExecPipeBufSetStatus(&pData->stdIn, false /* Disabled */); 584 VBoxServiceControlExecPipeBufSetStatus(&pData->stdOut, false /* Disabled */); 585 VBoxServiceControlExecPipeBufSetStatus(&pData->stdErr, false /* Disabled */); 586 583 587 /* Since the process is not alive anymore, destroy its local 584 588 * stdin pipe buffer - it's not used anymore and can eat up quite 585 589 * a bit of memory. */ 586 VBoxServiceControlExec DeletePipeBuffer(&pData->stdIn);590 VBoxServiceControlExecPipeBufDestroy(&pData->stdIn); 587 591 588 592 uint32_t uStatus = PROC_STS_UNDEFINED; … … 710 714 * pipe or not. 711 715 */ 712 static int VBoxServiceControlExec InitPipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe)716 static int VBoxServiceControlExecPipeBufInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe) 713 717 { 714 718 AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER); … … 720 724 pBuf->cbSize = 0; 721 725 pBuf->cbOffset = 0; 722 pBuf->f Alive= true;726 pBuf->fEnabled = true; 723 727 pBuf->fPendingClose = false; 724 728 pBuf->fNeedNotification = fNeedNotificationPipe; 725 729 pBuf->hNotificationPipeW = NIL_RTPIPE; 726 730 pBuf->hNotificationPipeR = NIL_RTPIPE; 727 728 int rc = RTCritSectInit(&pBuf->CritSect); 729 if (RT_SUCCESS(rc) && fNeedNotificationPipe) 730 { 731 rc = RTPipeCreate(&pBuf->hNotificationPipeR, &pBuf->hNotificationPipeW, 0); 732 if (RT_FAILURE(rc)) 733 RTCritSectDelete(&pBuf->CritSect); 734 } 735 return rc; 736 } 737 738 739 /** 740 * Deletes a pipe buffer. 741 * 742 * @param pBuf The pipe buffer. 743 */ 744 void VBoxServiceControlExecDeletePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf) 745 { 746 AssertPtr(pBuf); 747 if (pBuf->pbData) 748 { 749 RTMemFree(pBuf->pbData); 750 pBuf->pbData = NULL; 751 pBuf->cbAllocated = 0; 752 pBuf->cbSize = 0; 753 pBuf->cbOffset = 0; 754 pBuf->fAlive = false; 755 } 756 757 RTPipeClose(pBuf->hNotificationPipeR); 758 pBuf->hNotificationPipeR = NIL_RTPIPE; 759 RTPipeClose(pBuf->hNotificationPipeW); 760 pBuf->hNotificationPipeW = NIL_RTPIPE; 761 RTCritSectDelete(&pBuf->CritSect); 731 pBuf->hEventSem = NIL_RTSEMEVENT; 732 733 int rc = RTSemEventCreate(&pBuf->hEventSem); 734 if (RT_SUCCESS(rc)) 735 { 736 rc = RTCritSectInit(&pBuf->CritSect); 737 if (RT_SUCCESS(rc) && fNeedNotificationPipe) 738 { 739 rc = RTPipeCreate(&pBuf->hNotificationPipeR, &pBuf->hNotificationPipeW, 0); 740 if (RT_FAILURE(rc)) 741 RTCritSectDelete(&pBuf->CritSect); 742 } 743 } 744 return rc; 762 745 } 763 746 … … 773 756 * will reflect the actual amount read on return. 774 757 */ 775 int VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf,776 758 static int VBoxServiceControlExecPipeBufRead(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 759 uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead) 777 760 { 778 761 AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER); … … 795 778 memcpy(pbBuffer, pBuf->pbData + pBuf->cbOffset, *pcbToRead); 796 779 pBuf->cbOffset += *pcbToRead; 780 781 RTSemEventSignal(pBuf->hEventSem); 797 782 } 798 783 else … … 817 802 * @param pcbWritten Pointer to where the amount of written bytes get stored. Optional. 818 803 */ 819 int VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf,820 uint8_t *pbData, uint32_t cbData, bool fPendingClose,821 uint32_t *pcbWritten)804 static int VBoxServiceControlExecPipeBufWrite(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 805 uint8_t *pbData, uint32_t cbData, bool fPendingClose, 806 uint32_t *pcbWritten) 822 807 { 823 808 AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER); … … 825 810 826 811 int rc; 827 if (pBuf->f Alive)812 if (pBuf->fEnabled) 828 813 { 829 814 rc = RTCritSectEnter(&pBuf->CritSect); … … 885 870 if (RT_SUCCESS(rc)) 886 871 { 887 /* Report back written bytes (if wanted). */888 if (pcbWritten)889 *pcbWritten = cbData;890 891 872 /* 892 873 * Was this the final read/write to do on this buffer? Then close it … … 908 889 pBuf->fNeedNotification = !RT_SUCCESS(rc2); 909 890 } 891 892 /* Report back written bytes (if wanted). */ 893 if (pcbWritten) 894 *pcbWritten = cbData; 895 896 RTSemEventSignal(pBuf->hEventSem); 910 897 } 911 898 int rc2 = RTCritSectLeave(&pBuf->CritSect); … … 917 904 rc = VERR_BAD_PIPE; 918 905 return rc; 906 } 907 908 909 /** 910 * Returns whether a pipe buffer is active or not. 911 * 912 * @return bool True if pipe buffer is active, false if not. 913 * @param pBuf The pipe buffer. 914 */ 915 static bool VBoxServiceControlExecPipeBufIsEnabled(PVBOXSERVICECTRLEXECPIPEBUF pBuf) 916 { 917 AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER); 918 919 bool fEnabled = false; 920 if (RT_SUCCESS(RTCritSectEnter(&pBuf->CritSect))) 921 { 922 fEnabled = pBuf->fEnabled; 923 RTCritSectLeave(&pBuf->CritSect); 924 } 925 return fEnabled; 926 } 927 928 929 /** 930 * Sets the current status (enabled/disabled) of a pipe buffer. 931 * 932 * @return IPRT status code. 933 * @param pBuf The pipe buffer. 934 * @param fEnabled Pipe buffer status to set. 935 */ 936 static int VBoxServiceControlExecPipeBufSetStatus(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fEnabled) 937 { 938 AssertPtrReturn(pBuf, VERR_INVALID_PARAMETER); 939 940 int rc = RTCritSectEnter(&pBuf->CritSect); 941 if (RT_SUCCESS(rc)) 942 { 943 pBuf->fEnabled = fEnabled; 944 /* Let waiter know that something has changed ... */ 945 if (pBuf->hEventSem) 946 RTSemEventSignal(pBuf->hEventSem); 947 rc = RTCritSectLeave(&pBuf->CritSect); 948 } 949 return rc; 950 } 951 952 953 /** 954 * Deletes a pipe buffer. 955 * Note: Not thread safe -- only call this when nobody is relying on the 956 * data anymore! 957 * 958 * @param pBuf The pipe buffer. 959 */ 960 static void VBoxServiceControlExecPipeBufDestroy(PVBOXSERVICECTRLEXECPIPEBUF pBuf) 961 { 962 AssertPtr(pBuf); 963 if (pBuf->pbData) 964 { 965 RTMemFree(pBuf->pbData); 966 pBuf->pbData = NULL; 967 pBuf->cbAllocated = 0; 968 pBuf->cbSize = 0; 969 pBuf->cbOffset = 0; 970 } 971 972 RTPipeClose(pBuf->hNotificationPipeR); 973 pBuf->hNotificationPipeR = NIL_RTPIPE; 974 RTPipeClose(pBuf->hNotificationPipeW); 975 pBuf->hNotificationPipeW = NIL_RTPIPE; 976 977 RTSemEventDestroy(pBuf->hEventSem); 978 RTCritSectDelete(&pBuf->CritSect); 919 979 } 920 980 … … 1017 1077 1018 1078 /* Init buffers. */ 1019 rc = VBoxServiceControlExec InitPipeBuffer(&pData->stdOut, false /*fNeedNotificationPipe*/);1079 rc = VBoxServiceControlExecPipeBufInit(&pData->stdOut, false /*fNeedNotificationPipe*/); 1020 1080 if (RT_SUCCESS(rc)) 1021 1081 { 1022 rc = VBoxServiceControlExec InitPipeBuffer(&pData->stdErr, false /*fNeedNotificationPipe*/);1082 rc = VBoxServiceControlExecPipeBufInit(&pData->stdErr, false /*fNeedNotificationPipe*/); 1023 1083 if (RT_SUCCESS(rc)) 1024 rc = VBoxServiceControlExec InitPipeBuffer(&pData->stdIn, true /*fNeedNotificationPipe*/);1084 rc = VBoxServiceControlExecPipeBufInit(&pData->stdIn, true /*fNeedNotificationPipe*/); 1025 1085 } 1026 1086 } … … 1059 1119 RTStrFree(pData->pszPassword); 1060 1120 1061 VBoxServiceControlExec DeletePipeBuffer(&pData->stdOut);1062 VBoxServiceControlExec DeletePipeBuffer(&pData->stdErr);1063 VBoxServiceControlExec DeletePipeBuffer(&pData->stdIn);1121 VBoxServiceControlExecPipeBufDestroy(&pData->stdOut); 1122 VBoxServiceControlExecPipeBufDestroy(&pData->stdErr); 1123 VBoxServiceControlExecPipeBufDestroy(&pData->stdIn); 1064 1124 1065 1125 RTMemFree(pData); … … 1711 1771 */ 1712 1772 uint32_t cbWritten; 1713 rc = VBoxServiceControlExecWritePipeBuffer(&pData->stdIn, pabBuffer, cbSize, fPendingClose, &cbWritten); 1773 rc = VBoxServiceControlExecPipeBufWrite(&pData->stdIn, pabBuffer, 1774 cbSize, fPendingClose, &cbWritten); 1714 1775 #ifdef DEBUG 1715 1776 VBoxServiceVerbose(4, "ControlExec: Written to StdIn buffer (PID %u): rc=%Rrc, uFlags=0x%x, cbAlloc=%u, cbSize=%u, cbOffset=%u\n", … … 1787 1848 if (pBuf) 1788 1849 { 1789 /** @todo Use uHandleID to distinguish between stdout/stderr! */ 1790 rc = VBoxServiceControlExecReadPipeBufferContent(&pData->stdOut, pBuf, cbSize, &cbRead); 1850 /* If the stdout pipe buffer is enabled (that is, still could be filled by a running 1851 * process) wait for the signal to arrive so that we don't return without any actual 1852 * data read. */ 1853 if (VBoxServiceControlExecPipeBufIsEnabled(&pData->stdOut)) 1854 { 1855 VBoxServiceVerbose(4, "ControlExec: Waiting for output data becoming ready ...\n"); 1856 rc = RTSemEventWait(pData->stdOut.hEventSem, RT_INDEFINITE_WAIT); 1857 } 1791 1858 if (RT_SUCCESS(rc)) 1792 1859 { 1793 /* Note: Since the context ID is unique the request *has* to be completed here, 1794 * regardless whether we got data or not! Otherwise the progress object 1795 * on the host never will get completed! */ 1796 /* cbRead now contains actual size. */ 1797 rc = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, 0 /* Handle ID */, 0 /* Flags */, 1798 pBuf, cbRead); 1860 /** @todo Use uHandleID to distinguish between stdout/stderr! */ 1861 rc = VBoxServiceControlExecPipeBufRead(&pData->stdOut, pBuf, cbSize, &cbRead); 1862 if (RT_SUCCESS(rc)) 1863 { 1864 /* Note: Since the context ID is unique the request *has* to be completed here, 1865 * regardless whether we got data or not! Otherwise the progress object 1866 * on the host never will get completed! */ 1867 /* cbRead now contains actual size. */ 1868 rc = VbglR3GuestCtrlExecSendOut(u32ClientId, uContextID, uPID, 0 /* Handle ID */, 0 /* Flags */, 1869 pBuf, cbRead); 1870 } 1799 1871 } 1800 1872 RTMemFree(pBuf); -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r34867 r35952 5 5 6 6 /* 7 * Copyright (C) 2007-201 0Oracle Corporation7 * Copyright (C) 2007-2011 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 136 136 /** Critical section protecting this buffer structure. */ 137 137 RTCRITSECT CritSect; 138 /** Indicates the health condition of the child process. */ 139 bool fAlive; 138 /** Flag indicating whether this pipe buffer accepts new 139 * data to be written to or not. If not enabled, already 140 * (allocated) buffered data still can be read out. */ 141 bool fEnabled; 140 142 /** Set if it's necessary to write to the notification pipe. */ 141 143 bool fNeedNotification; … … 147 149 /** The other end of hNotificationPipeW. */ 148 150 RTPIPE hNotificationPipeR; 151 /** The event semaphore for getting notified whether something 152 * has changed, e.g. written or read from this buffer. */ 153 RTSEMEVENT hEventSem; 149 154 } VBOXSERVICECTRLEXECPIPEBUF; 150 155 /** Pointer to buffered pipe data. */ … … 299 304 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS); 300 305 extern void VBoxServiceControlExecDestroyThreadData(PVBOXSERVICECTRLTHREADDATAEXEC pThread); 301 extern void VBoxServiceControlExecDeletePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf); 302 extern int VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 303 uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead); 304 extern int VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 305 uint8_t *pbData, uint32_t cbData, bool fPendingClose, uint32_t *pcbWritten); 306 307 extern int VBoxServiceControlExecPipeInit(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fNeedNotificationPipe); 308 extern int VBoxServiceControlExecPipeBufRead(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 309 uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead); 310 extern int VBoxServiceControlExecPipeBufWrite(PVBOXSERVICECTRLEXECPIPEBUF pBuf, 311 uint8_t *pbData, uint32_t cbData, bool fPendingClose, uint32_t *pcbWritten); 312 extern bool VBoxServiceControlExecPipeBufIsEnabled(PVBOXSERVICECTRLEXECPIPEBUF pBuf); 313 extern int VBoxServiceControlExecPipeBufSetStatus(PVBOXSERVICECTRLEXECPIPEBUF pBuf, bool fEnabled); 314 extern void VBoxServiceControlExecPipeBufDestroy(PVBOXSERVICECTRLEXECPIPEBUF pBuf); 306 315 #endif /* VBOX_WITH_GUEST_CONTROL */ 307 316
Note:
See TracChangeset
for help on using the changeset viewer.