Changeset 39434 in vbox for trunk/src/VBox/Additions
- Timestamp:
- Nov 28, 2011 12:51:34 PM (13 years ago)
- svn:sync-xref-src-repo-rev:
- 75067
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp
r39427 r39434 23 23 #include <iprt/assert.h> 24 24 #include <iprt/env.h> 25 #include <iprt/file.h> 25 26 #include <iprt/getopt.h> 26 27 #include <iprt/handle.h> … … 389 390 { 390 391 int rc = VINF_SUCCESS; 391 if (fPollEvt == RTPOLL_EVT_READ) 392 { 393 /** @todo r=bird: Drop this in favor of using /dev/null 394 * (RTFileOpenBitBucket) instead of pipes. That'll simplify the code, 395 * speed stuff up, avoid trouble is RTPoll is buggy and be 396 * compatible with future wait-for-writeable-stderr/out host 397 * notifications. */ 398 char abBuf[_64K]; 399 size_t cbRead; 400 rc = RTPipeRead(*phPipeR, abBuf, sizeof(abBuf), &cbRead); 401 if (RT_SUCCESS(rc) && cbRead) 402 { 403 #ifdef DEBUG 404 VBoxServiceVerbose(4, "ControlThread: Drain idPollHnd=%u, abBuf=0x%p, cbRead=%u\n", 405 idPollHnd, abBuf, cbRead); 406 #endif 407 /* Goes to bit bucket ... */ 408 409 /* Make sure we go another poll round in case there was too much data 410 for the buffer to hold. */ 411 fPollEvt &= RTPOLL_EVT_ERROR; 412 } 413 else if (RT_FAILURE(rc)) 414 { 415 fPollEvt |= RTPOLL_EVT_ERROR; 416 AssertMsg(rc == VERR_BROKEN_PIPE, ("%Rrc\n", rc)); 417 } 392 393 if (fPollEvt & RTPOLL_EVT_READ) 394 { 395 396 /* Make sure we go another poll round in case there was too much data 397 for the buffer to hold. */ 398 fPollEvt &= RTPOLL_EVT_ERROR; 418 399 } 419 400 … … 602 583 uint32_t idPollHnd; 603 584 uint32_t fPollEvt; 604 rc2 = RTPollNoResume(hPollSet, /*cMsPollCur*/ RT_INDEFINITE_WAIT, &fPollEvt, &idPollHnd);585 rc2 = RTPollNoResume(hPollSet, cMsPollCur, &fPollEvt, &idPollHnd); 605 586 if (pThread->fShutdown) 606 587 continue; … … 640 621 break; /* We were asked to shutdown. */ 641 622 642 /* Do we have more to poll for (e.g. is there (still) something in our pollset 643 * like stdout, stderr or stdin)? If we only have our notification pipe left we 644 * need to bail out. */ 645 if (RTPollSetGetCount(hPollSet) > 1) 646 continue; 623 continue; 647 624 } 648 625 … … 858 835 * 859 836 * @returns IPRT status code. No client replies made. 837 * @param pszHowTo How to set up this standard handle. 860 838 * @param fd Which standard handle it is (0 == stdin, 1 == 861 839 * stdout, 2 == stderr). … … 865 843 * Always set. 866 844 * @param phPipe Where to return the end of the pipe that we 867 * should service. Always set. 868 * 869 * @todo r=bird: Open the bitbucket like txsDoExecHlpRedir does when the host 870 * isn't interested in the guest output. This is easier to handle 871 * elsewhere. 872 */ 873 static int VBoxServiceControlThreadSetupPipe(int fd, PRTHANDLE ph, PRTHANDLE *pph, PRTPIPE phPipe) 874 { 875 AssertPtrReturn(ph, VERR_INVALID_PARAMETER); 876 AssertPtrReturn(pph, VERR_INVALID_PARAMETER); 877 AssertPtrReturn(phPipe, VERR_INVALID_PARAMETER); 845 * should service. 846 */ 847 static int VBoxServiceControlThreadSetupPipe(const char *pszHowTo, int fd, 848 PRTHANDLE ph, PRTHANDLE *pph, PRTPIPE phPipe) 849 { 850 AssertPtrReturn(ph, VERR_INVALID_POINTER); 851 AssertPtrReturn(ph, VERR_INVALID_POINTER); 852 AssertPtrReturn(pph, VERR_INVALID_POINTER); 878 853 879 854 int rc; 880 855 881 /*882 * Setup a pipe for forwarding to/from the client.883 * The ph union struct will be filled with a pipe read/write handle884 * to represent the "other" end to phPipe.885 */886 if (fd == 0) /* stdin? */887 {888 /* Connect a wrtie pipe specified by phPipe to stdin. */889 rc = RTPipeCreate(&ph->u.hPipe, phPipe, RTPIPE_C_INHERIT_READ);890 }891 else /* stdout or stderr? */892 {893 /* Connect a read pipe specified by phPipe to stdout or stderr. */894 rc = RTPipeCreate(phPipe, &ph->u.hPipe, RTPIPE_C_INHERIT_WRITE);895 }896 if (RT_FAILURE(rc))897 return rc;898 856 ph->enmType = RTHANDLETYPE_PIPE; 899 *pph = ph; 857 ph->u.hPipe = NIL_RTPIPE; 858 *pph = NULL; 859 *phPipe = NIL_RTPIPE; 860 861 if (!strcmp(pszHowTo, "|")) 862 { 863 /* 864 * Setup a pipe for forwarding to/from the client. 865 * The ph union struct will be filled with a pipe read/write handle 866 * to represent the "other" end to phPipe. 867 */ 868 if (fd == 0) /* stdin? */ 869 { 870 /* Connect a wrtie pipe specified by phPipe to stdin. */ 871 rc = RTPipeCreate(&ph->u.hPipe, phPipe, RTPIPE_C_INHERIT_READ); 872 } 873 else /* stdout or stderr? */ 874 { 875 /* Connect a read pipe specified by phPipe to stdout or stderr. */ 876 rc = RTPipeCreate(phPipe, &ph->u.hPipe, RTPIPE_C_INHERIT_WRITE); 877 } 878 879 if (RT_FAILURE(rc)) 880 return rc; 881 882 ph->enmType = RTHANDLETYPE_PIPE; 883 *pph = ph; 884 } 885 else if (!strcmp(pszHowTo, "/dev/null")) 886 { 887 /* 888 * Redirect to/from /dev/null. 889 */ 890 RTFILE hFile; 891 rc = RTFileOpenBitBucket(&hFile, fd == 0 ? RTFILE_O_READ : RTFILE_O_WRITE); 892 if (RT_FAILURE(rc)) 893 return rc; 894 895 ph->enmType = RTHANDLETYPE_FILE; 896 ph->u.hFile = hFile; 897 *pph = ph; 898 } 899 else /* Add other piping stuff here. */ 900 rc = VERR_INVALID_PARAMETER; 900 901 901 902 return rc; … … 1191 1192 RTHANDLE hStdIn; 1192 1193 PRTHANDLE phStdIn; 1193 rc = VBoxServiceControlThreadSetupPipe(0 /*STDIN_FILENO*/, &hStdIn, &phStdIn, &pThread->pipeStdInW); 1194 rc = VBoxServiceControlThreadSetupPipe("|", 0 /*STDIN_FILENO*/, 1195 &hStdIn, &phStdIn, &pThread->pipeStdInW); 1194 1196 if (RT_SUCCESS(rc)) 1195 1197 { … … 1197 1199 PRTHANDLE phStdOut; 1198 1200 RTPIPE hStdOutR; 1199 rc = VBoxServiceControlThreadSetupPipe(1 /*STDOUT_FILENO*/, &hStdOut, &phStdOut, &hStdOutR); 1201 rc = VBoxServiceControlThreadSetupPipe( (pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDOUT) 1202 ? "|" : "/dev/null", 1203 1 /*STDOUT_FILENO*/, 1204 &hStdOut, &phStdOut, &hStdOutR); 1200 1205 if (RT_SUCCESS(rc)) 1201 1206 { … … 1203 1208 PRTHANDLE phStdErr; 1204 1209 RTPIPE hStdErrR; 1205 rc = VBoxServiceControlThreadSetupPipe(2 /*STDERR_FILENO*/, &hStdErr, &phStdErr, &hStdErrR); 1210 rc = VBoxServiceControlThreadSetupPipe( (pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDERR) 1211 ? "|" : "/dev/null", 1212 2 /*STDERR_FILENO*/, 1213 &hStdErr, &phStdErr, &hStdErrR); 1206 1214 if (RT_SUCCESS(rc)) 1207 1215 { … … 1219 1227 /* Stdout. */ 1220 1228 if (RT_SUCCESS(rc)) 1221 { 1222 uint32_t uFlags = RTPOLL_EVT_ERROR; 1223 if (!(pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDOUT)) 1224 { 1225 uFlags |= RTPOLL_EVT_READ; 1226 VBoxServiceVerbose(3, "ControlThread: Host is not interested in getting stdout for \"%s\", poll flags=0x%x\n", 1227 pThread->pszCmd, uFlags); 1228 } 1229 rc = RTPollSetAddPipe(hPollSet, hStdOutR, uFlags, VBOXSERVICECTRLPIPEID_STDOUT); 1230 } 1229 rc = RTPollSetAddPipe(hPollSet, hStdOutR, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDOUT); 1231 1230 /* Stderr. */ 1232 1231 if (RT_SUCCESS(rc)) 1233 { 1234 uint32_t uFlags = RTPOLL_EVT_ERROR; 1235 if (!(pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDERR)) 1236 { 1237 uFlags |= RTPOLL_EVT_READ; 1238 VBoxServiceVerbose(3, "ControlThread: Host is not interested in getting stderr for \"%s\", poll flags=0x%x\n", 1239 pThread->pszCmd, uFlags); 1240 } 1241 rc = RTPollSetAddPipe(hPollSet, hStdErrR, uFlags, VBOXSERVICECTRLPIPEID_STDERR); 1242 } 1232 rc = RTPollSetAddPipe(hPollSet, hStdErrR, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDERR); 1243 1233 /* IPC notification pipe. */ 1244 1234 if (RT_SUCCESS(rc))
Note:
See TracChangeset
for help on using the changeset viewer.