Changeset 45697 in vbox
- Timestamp:
- Apr 24, 2013 1:30:50 PM (12 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h
r45604 r45697 97 97 /** Event semaphore to serialize access. */ 98 98 RTSEMEVENTMULTI Event; 99 /** Flag indicating if this request is asynchronous or not. */ 99 /** Flag indicating if this request is asynchronous or not. 100 * If asynchronous, this request will be deleted automatically 101 * on completion. Otherwise the caller has to delete the 102 * request again. */ 100 103 bool fAsync; 101 104 /** The request type to handle. */ … … 313 316 /** Node. */ 314 317 RTLISTNODE Node; 318 /** Number of references using this struct. */ 319 uint32_t cRefs; 315 320 /** The worker thread. */ 316 321 RTTHREAD Thread; -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlProcess.cpp
r45610 r45697 47 47 *******************************************************************************/ 48 48 static int gstcntlProcessAssignPID(PVBOXSERVICECTRLPROCESS pThread, uint32_t uPID); 49 static int gstcntlProcessLock(PVBOXSERVICECTRLPROCESS pProcess); 49 50 static int gstcntlProcessRequestCancel(PVBOXSERVICECTRLREQUEST pThread); 50 51 static int gstcntlProcessSetupPipe(const char *pszHowTo, int fd, PRTHANDLE ph, PRTHANDLE *pph, PRTPIPE phPipe); 52 static int gstcntlProcessUnlock(PVBOXSERVICECTRLPROCESS pProcess); 51 53 52 54 /** … … 148 150 pProcess->uPID); 149 151 152 /* Do *not* set pThread->fShutdown or other stuff here! 153 * The guest thread loop will do that as soon as it processes the quit message. */ 154 155 PVBOXSERVICECTRLREQUEST pRequest; 156 int rc = GstCntlProcessRequestAlloc(&pRequest, VBOXSERVICECTRLREQUEST_PROC_TERM); 157 if (RT_SUCCESS(rc)) 158 { 159 rc = GstCntlProcessPerform(pProcess, pRequest, 160 true /* Async */); 161 if (RT_FAILURE(rc)) 162 VBoxServiceVerbose(3, "[PID %RU32]: Sending termination request failed with rc=%Rrc\n", 163 pProcess->uPID, rc); 164 /* Deletion of pRequest will be done on request completion (asynchronous). */ 165 } 166 167 return rc; 168 } 169 170 171 /** 172 * Releases a previously acquired guest process (decreses the refcount). 173 * 174 * @param pProcess Process to unlock. 175 */ 176 void GstCntlProcessRelease(const PVBOXSERVICECTRLPROCESS pProcess) 177 { 178 AssertPtrReturnVoid(pProcess); 179 150 180 int rc = RTCritSectEnter(&pProcess->CritSect); 151 181 if (RT_SUCCESS(rc)) 152 182 { 153 if (pProcess->pRequest) 154 { 155 rc = gstcntlProcessRequestCancel(pProcess->pRequest); 156 if (RT_FAILURE(rc)) 157 VBoxServiceError("[PID %RU32]: Cancelling current request failed, rc=%Rrc\n", 158 pProcess->uPID, rc); 159 } 160 161 /* Do *not* set pThread->fShutdown or other stuff here! 162 * The guest thread loop will do that as soon as it processes the quit message. */ 163 164 PVBOXSERVICECTRLREQUEST pRequest; 165 rc = GstCntlProcessRequestAlloc(&pRequest, VBOXSERVICECTRLREQUEST_PROC_TERM); 166 if (RT_SUCCESS(rc)) 167 { 168 rc = GstCntlProcessPerform(pProcess, pRequest, 169 true /* Async */); 170 if (RT_FAILURE(rc)) 171 VBoxServiceVerbose(3, "[PID %RU32]: Sending termination request failed with rc=%Rrc\n", 172 pProcess->uPID, rc); 173 /* Deletion of pRequest will be done on request completion. */ 174 } 175 176 int rc2 = RTCritSectLeave(&pProcess->CritSect); 177 AssertRC(rc2); 178 } 179 180 return rc; 181 } 182 183 184 /** 185 * Releases (unlocks) a previously locked guest process. 186 * 187 * @param pProcess Process to unlock. 188 */ 189 void GstCntlProcessRelease(const PVBOXSERVICECTRLPROCESS pProcess) 190 { 191 AssertPtrReturnVoid(pProcess); 192 193 int rc = RTCritSectLeave(&pProcess->CritSect); 194 AssertRC(rc); 183 Assert(pProcess->cRefs); 184 pProcess->cRefs--; 185 rc = RTCritSectLeave(&pProcess->CritSect); 186 AssertRC(rc); 187 } 195 188 } 196 189 … … 269 262 270 263 264 static const char* gstcntlProcessPollHandleToString(uint32_t idPollHnd) 265 { 266 switch (idPollHnd) 267 { 268 case VBOXSERVICECTRLPIPEID_UNKNOWN: 269 return "unknown"; 270 case VBOXSERVICECTRLPIPEID_STDIN: 271 return "stdin"; 272 case VBOXSERVICECTRLPIPEID_STDIN_WRITABLE: 273 return "stdin_writable"; 274 case VBOXSERVICECTRLPIPEID_STDOUT: 275 return "stdout"; 276 case VBOXSERVICECTRLPIPEID_STDERR: 277 return "stderr"; 278 case VBOXSERVICECTRLPIPEID_IPC_NOTIFY: 279 return "ipc_notify"; 280 default: 281 break; 282 } 283 284 return "unknown"; 285 } 286 287 271 288 /** 272 289 * Handle an error event on standard input. … … 301 318 302 319 #ifdef DEBUG 303 VBoxServiceVerbose(4, "gstcntlProcessHandleOutputError: fPollEvt=0x%x, idPollHnd=% u\n",304 fPollEvt, idPollHnd);320 VBoxServiceVerbose(4, "gstcntlProcessHandleOutputError: fPollEvt=0x%x, idPollHnd=%s\n", 321 fPollEvt, gstcntlProcessPollHandleToString(idPollHnd)); 305 322 #endif 306 323 … … 317 334 && cbReadable) 318 335 { 319 VBoxServiceVerbose(3, "gstcntlProcessHandleOutputError: idPollHnd=% RU32has %zu bytes left, vetoing close\n",320 idPollHnd, cbReadable);336 VBoxServiceVerbose(3, "gstcntlProcessHandleOutputError: idPollHnd=%s has %zu bytes left, vetoing close\n", 337 gstcntlProcessPollHandleToString(idPollHnd), cbReadable); 321 338 322 339 /* Veto closing the pipe yet because there's still stuff to read … … 326 343 } 327 344 else 328 VBoxServiceVerbose(3, "gstcntlProcessHandleOutputError: idPollHnd=% RU32will be closed\n",329 idPollHnd);345 VBoxServiceVerbose(3, "gstcntlProcessHandleOutputError: idPollHnd=%s will be closed\n", 346 gstcntlProcessPollHandleToString(idPollHnd)); 330 347 331 348 if ( *phPipeR != NIL_RTPIPE … … 354 371 PRTPIPE phPipeR, uint32_t idPollHnd) 355 372 { 356 #if 0357 VBoxServiceVerbose(4, "GstCntlProcessHandleOutputEvent: fPollEvt=0x%x, idPollHnd=% u\n",358 fPollEvt, idPollHnd);373 #ifdef DEBUG_andy 374 VBoxServiceVerbose(4, "GstCntlProcessHandleOutputEvent: fPollEvt=0x%x, idPollHnd=%s\n", 375 fPollEvt, gstcntlProcessPollHandleToString(idPollHnd)); 359 376 #endif 360 377 … … 439 456 440 457 441 static int gstcntlProcessRequestHandle( RTPOLLSET hPollSet, uint32_t fPollEvt,442 PRTPIPE phStdInW, PRTPIPE phStdOutR, PRTPIPE phStdErrR,443 P VBOXSERVICECTRLPROCESS pProcess, PVBOXSERVICECTRLREQUEST pRequest)458 static int gstcntlProcessRequestHandle(PVBOXSERVICECTRLPROCESS pProcess, PVBOXSERVICECTRLREQUEST pRequest, 459 RTPOLLSET hPollSet, uint32_t fPollEvt, 460 PRTPIPE phStdInW, PRTPIPE phStdOutR, PRTPIPE phStdErrR) 444 461 { 445 462 AssertPtrReturn(phStdInW, VERR_INVALID_POINTER); … … 530 547 531 548 case VBOXSERVICECTRLREQUEST_PROC_TERM: 532 ASMAtomicXchgBool(&pProcess->fShutdown, true);549 pProcess->fShutdown = true; 533 550 fDefer = true; 534 551 break; … … 605 622 pProcess->uPID, pProcess->StartupInfo.szCmd, pProcess->uContextID, 606 623 pProcess->StartupInfo.szUser, pProcess->StartupInfo.uTimeLimitMS); 607 VBGLR3GUESTCTRLCMDCTX ctx = { pProcess->uClientID, pProcess->uContextID };608 rc = VbglR3GuestCtrlProcCbStatus(&ctx ,624 VBGLR3GUESTCTRLCMDCTX ctxStart = { pProcess->uClientID, pProcess->uContextID }; 625 rc = VbglR3GuestCtrlProcCbStatus(&ctxStart, 609 626 pProcess->uPID, PROC_STS_STARTED, 0 /* u32Flags */, 610 627 NULL /* pvData */, 0 /* cbData */); … … 613 630 * Process input, output, the test pipe and client requests. 614 631 */ 615 PVBOXSERVICECTRLREQUEST pReq = NULL;616 632 while ( RT_SUCCESS(rc) 617 633 && RT_UNLIKELY(!pProcess->fShutdown)) … … 640 656 phStdOutR, idPollHnd); 641 657 break; 658 642 659 case VBOXSERVICECTRLPIPEID_STDERR: 643 660 rc = gstcntlProcessHandleOutputEvent(hPollSet, fPollEvt, … … 646 663 647 664 case VBOXSERVICECTRLPIPEID_IPC_NOTIFY: 648 pReq = pProcess->pRequest; /** @todo Implement request queue. */ 649 rc = gstcntlProcessRequestHandle(hPollSet, fPollEvt, 650 phStdInW, phStdOutR, phStdErrR, 651 pProcess, pReq); 652 if (rc == VINF_AIO_TASK_PENDING) 653 VBoxServiceVerbose(4, "[PID %RU32]: pRequest=%p will be handled deferred\n", 654 pProcess->uPID, pReq); 665 #ifdef DEBUG_andy 666 VBoxServiceVerbose(4, "[PID %RU32]: IPC notify\n", pProcess->uPID); 667 #endif 668 rc = gstcntlProcessLock(pProcess); 669 if (RT_SUCCESS(rc)) 670 { 671 /** @todo Implement request queue. */ 672 rc = gstcntlProcessRequestHandle(pProcess, pProcess->pRequest, 673 hPollSet, fPollEvt, 674 phStdInW, phStdOutR, phStdErrR); 675 if (rc != VINF_AIO_TASK_PENDING) 676 { 677 pProcess->pRequest = NULL; 678 } 679 else 680 VBoxServiceVerbose(4, "[PID %RU32]: pRequest=%p will be handled deferred\n", 681 pProcess->uPID, pProcess->pRequest); 682 683 rc2 = gstcntlProcessUnlock(pProcess); 684 AssertRC(rc2); 685 } 655 686 break; 656 687 … … 664 695 } 665 696 #ifdef DEBUG_andy 666 VBoxServiceVerbose(4, "[PID %RU32]: Polling done, pollRc=%Rrc, pollCnt=%u, idPollHnd=%RU32, rc=%Rrc, fProcessAlive=%RTbool, fShutdown=%RTbool\n", 667 pProcess->uPID, rc2, RTPollSetGetCount(hPollSet), idPollHnd, rc, fProcessAlive, pProcess->fShutdown); 697 VBoxServiceVerbose(4, "[PID %RU32]: Polling done, pollRc=%Rrc, pollCnt=%RU32, idPollHnd=%s, rc=%Rrc, fProcessAlive=%RTbool, fShutdown=%RTbool\n", 698 pProcess->uPID, rc2, RTPollSetGetCount(hPollSet), gstcntlProcessPollHandleToString(idPollHnd), rc, fProcessAlive, pProcess->fShutdown); 699 VBoxServiceVerbose(4, "[PID %RU32]: stdOut=%s, stdErrR=%s\n", 700 pProcess->uPID, 701 *phStdOutR == NIL_RTPIPE ? "closed" : "open", 702 *phStdErrR == NIL_RTPIPE ? "closed" : "open"); 668 703 #endif 669 704 if (RT_UNLIKELY(pProcess->fShutdown)) … … 677 712 rc2 = RTProcWaitNoResume(hProcess, RTPROCWAIT_FLAGS_NOBLOCK, &ProcessStatus); 678 713 #ifdef DEBUG_andy 679 VBoxServiceVerbose(4, "[PID %RU32]: RTProcWaitNoResume=%Rrc, stdOut=%s, stdErrR=%s\n", 680 pProcess->uPID, rc2, 681 *phStdOutR == NIL_RTPIPE ? "closed" : "open", 682 *phStdErrR == NIL_RTPIPE ? "closed" : "open"); 714 VBoxServiceVerbose(4, "[PID %RU32]: RTProcWaitNoResume=%Rrc\n", 715 pProcess->uPID, rc2); 683 716 #endif 684 717 if (RT_SUCCESS_NP(rc2)) … … 707 740 && *phStdOutR == NIL_RTPIPE 708 741 && *phStdErrR == NIL_RTPIPE) 742 { 743 VBoxServiceVerbose(3, "[PID %RU32]: All pipes closed, process not alive anymore, bailing out ...\n", 744 pProcess->uPID); 709 745 break; 746 } 710 747 711 748 /* … … 713 750 */ 714 751 uint32_t cMilliesLeft = RT_INDEFINITE_WAIT; 715 if (pProcess->StartupInfo.uTimeLimitMS != RT_INDEFINITE_WAIT) 752 if ( pProcess->StartupInfo.uTimeLimitMS != RT_INDEFINITE_WAIT 753 && pProcess->StartupInfo.uTimeLimitMS != 0) 716 754 { 717 755 uint64_t u64Now = RTTimeMilliTS(); … … 746 784 } 747 785 748 rc2 = RTCritSectEnter(&pProcess->CritSect); 749 if (RT_SUCCESS(rc2)) 750 { 751 ASMAtomicXchgBool(&pProcess->fShutdown, true); 752 753 rc2 = RTCritSectLeave(&pProcess->CritSect); 754 AssertRC(rc2); 755 } 786 VBoxServiceVerbose(2, "[PID %RU32]: Process loop ended with rc=%Rrc\n", 787 pProcess->uPID, rc); 788 789 /* Signal that this thread is in progress of shutting down. */ 790 ASMAtomicXchgBool(&pProcess->fShutdown, true); 756 791 757 792 /* … … 762 797 if (MsProcessKilled == UINT64_MAX) 763 798 { 764 VBoxServiceVerbose( 3, "[PID %RU32]: Is still alive and not killed yet\n",799 VBoxServiceVerbose(2, "[PID %RU32]: Is still alive and not killed yet\n", 765 800 pProcess->uPID); 766 801 767 802 MsProcessKilled = RTTimeMilliTS(); 768 RTProcTerminate(hProcess); 803 rc2 = RTProcTerminate(hProcess); 804 if (RT_FAILURE(rc)) 805 VBoxServiceError("PID %RU32]: Killing process failed with rc=%Rrc\n", 806 pProcess->uPID, rc); 769 807 RTThreadSleep(500); 770 808 } … … 786 824 VBoxServiceVerbose(4, "[PID %RU32]: Kill attempt %d/10: Trying to terminate ...\n", 787 825 pProcess->uPID, i + 1); 788 RTProcTerminate(hProcess); 826 rc2 = RTProcTerminate(hProcess); 827 if (RT_FAILURE(rc)) 828 VBoxServiceError("PID %RU32]: Killing process failed with rc=%Rrc\n", 829 pProcess->uPID, rc); 789 830 } 790 831 RTThreadSleep(i >= 5 ? 2000 : 500); … … 792 833 793 834 if (fProcessAlive) 794 VBoxServiceVerbose(3, "[PID %RU32]: Could not be killed\n", pProcess->uPID); 795 796 if ( pReq /* Handle deferred termination request. */ 797 && pReq->enmType == VBOXSERVICECTRLREQUEST_PROC_TERM) 798 { 799 rc2 = gstcntlProcessRequestComplete(pReq, 800 fProcessAlive ? VINF_SUCCESS : VERR_PROCESS_RUNNING); 801 AssertRC(rc2); 802 } 803 else if (pReq) 804 AssertMsgFailed(("Unable to handle unknown deferred request (type: %RU32)\n", pReq->enmType)); 835 VBoxServiceError("[PID %RU32]: Could not be killed\n", pProcess->uPID); 836 } 837 838 rc2 = gstcntlProcessLock(pProcess); 839 if (RT_SUCCESS(rc2)) 840 { 841 if (pProcess->pRequest) 842 { 843 switch (pProcess->pRequest->enmType) 844 { 845 /* Handle deferred termination request. */ 846 case VBOXSERVICECTRLREQUEST_PROC_TERM: 847 rc2 = gstcntlProcessRequestComplete(pProcess->pRequest, 848 fProcessAlive ? VINF_SUCCESS : VERR_PROCESS_RUNNING); 849 AssertRC(rc2); 850 break; 851 852 /* Cancel all others. 853 ** @todo Clear request queue as soon as it's implemented. */ 854 default: 855 rc2 = gstcntlProcessRequestCancel(pProcess->pRequest); 856 AssertRC(rc2); 857 break; 858 } 859 860 pProcess->pRequest = NULL; 861 } 862 #ifdef DEBUG 863 else 864 VBoxServiceVerbose(3, "[PID %RU32]: No pending request found\n", pProcess->uPID); 865 #endif 866 rc2 = gstcntlProcessUnlock(pProcess); 867 AssertRC(rc2); 805 868 } 806 869 … … 877 940 if (!(pProcess->StartupInfo.uFlags & EXECUTEPROCESSFLAG_WAIT_START)) 878 941 { 879 VBGLR3GUESTCTRLCMDCTX ctx = { pProcess->uClientID, pProcess->uContextID };880 rc2 = VbglR3GuestCtrlProcCbStatus(&ctx ,942 VBGLR3GUESTCTRLCMDCTX ctxEnd = { pProcess->uClientID, pProcess->uContextID }; 943 rc2 = VbglR3GuestCtrlProcCbStatus(&ctxEnd, 881 944 pProcess->uPID, uStatus, uFlags, 882 945 NULL /* pvData */, 0 /* cbData */); … … 890 953 } 891 954 892 VBoxServiceVerbose(3, "[PID %RU32]: Process loop ended with rc=%Rrc\n",955 VBoxServiceVerbose(3, "[PID %RU32]: Process loop returned with rc=%Rrc\n", 893 956 pProcess->uPID, rc); 894 957 return rc; … … 993 1056 return VINF_SUCCESS; 994 1057 995 VBoxServiceVerbose(4, "Cancelling request=0x%p\n", pReq);1058 VBoxServiceVerbose(4, "Cancelling outstanding request=0x%p\n", pReq); 996 1059 997 1060 return RTSemEventMultiSignal(pReq->Event); … … 1034 1097 if (RT_SUCCESS(rc)) 1035 1098 { 1036 VBoxServiceVerbose(4, "Performed request with rc=%Rrc, cbData=% u\n",1099 VBoxServiceVerbose(4, "Performed request with rc=%Rrc, cbData=%RU32\n", 1037 1100 pReq->rc, pReq->cbData); 1038 1101 … … 1783 1846 1784 1847 1848 static int gstcntlProcessLock(PVBOXSERVICECTRLPROCESS pProcess) 1849 { 1850 AssertPtrReturn(pProcess, VERR_INVALID_POINTER); 1851 int rc = RTCritSectEnter(&pProcess->CritSect); 1852 AssertRC(rc); 1853 return rc; 1854 } 1855 1856 1785 1857 /** 1786 1858 * Thread main routine for a started process. … … 1796 1868 AssertPtrReturn(pProcess, VERR_INVALID_POINTER); 1797 1869 return gstcntlProcessProcessWorker(pProcess); 1870 } 1871 1872 1873 static int gstcntlProcessUnlock(PVBOXSERVICECTRLPROCESS pProcess) 1874 { 1875 AssertPtrReturn(pProcess, VERR_INVALID_POINTER); 1876 int rc = RTCritSectLeave(&pProcess->CritSect); 1877 AssertRC(rc); 1878 return rc; 1798 1879 } 1799 1880 … … 1884 1965 int rc = VINF_SUCCESS; 1885 1966 1886 AssertMsgReturn(pProcess->pRequest == NULL,1887 ("Another request still is in progress (%p)\n", pProcess->pRequest),1888 VERR_ACCESS_DENIED);1889 1890 1967 if ( ASMAtomicReadBool(&pProcess->fShutdown) 1891 1968 || ASMAtomicReadBool(&pProcess->fStopped)) … … 1895 1972 else 1896 1973 { 1897 VBoxServiceVerbose(3, "[PID %RU32]: Sending pRequest=%p\n", 1898 pProcess->uPID, pRequest); 1899 1900 /* Set request structure pointer. */ 1901 pProcess->pRequest = pRequest; 1902 1903 /** @todo To speed up simultaneous guest process handling we could add a worker threads 1904 * or queue in order to wait for the request to happen. Later. */ 1905 /* Wake up guest thread by sending a wakeup byte to the notification pipe so 1906 * that RTPoll unblocks (returns) and we then can do our requested operation. */ 1907 Assert(pProcess->hNotificationPipeW != NIL_RTPIPE); 1908 size_t cbWritten = 0; 1974 rc = gstcntlProcessLock(pProcess); 1909 1975 if (RT_SUCCESS(rc)) 1910 rc = RTPipeWrite(pProcess->hNotificationPipeW, "i", 1, &cbWritten); 1911 1912 if (RT_SUCCESS(rc)) 1913 { 1914 Assert(cbWritten); 1915 if (!fAsync) 1976 { 1977 AssertMsgReturn(pProcess->pRequest == NULL, 1978 ("Another request still is in progress (%p)\n", pProcess->pRequest), 1979 VERR_ALREADY_EXISTS); 1980 1981 VBoxServiceVerbose(3, "[PID %RU32]: Sending pRequest=%p\n", 1982 pProcess->uPID, pRequest); 1983 1984 /* Set request structure pointer. */ 1985 pProcess->pRequest = pRequest; 1986 1987 /** @todo To speed up simultaneous guest process handling we could add a worker threads 1988 * or queue in order to wait for the request to happen. Later. */ 1989 /* Wake up guest thread by sending a wakeup byte to the notification pipe so 1990 * that RTPoll unblocks (returns) and we then can do our requested operation. */ 1991 Assert(pProcess->hNotificationPipeW != NIL_RTPIPE); 1992 size_t cbWritten = 0; 1993 if (RT_SUCCESS(rc)) 1994 rc = RTPipeWrite(pProcess->hNotificationPipeW, "i", 1, &cbWritten); 1995 1996 int rcWait = VINF_SUCCESS; 1997 if (RT_SUCCESS(rc)) 1916 1998 { 1917 VBoxServiceVerbose(3, "[PID %RU32]: Waiting for response on pRequest=%p, enmType=%u, pvData=0x%p, cbData=%u\n", 1918 pProcess->uPID, pRequest, pRequest->enmType, pRequest->pvData, pRequest->cbData); 1919 1920 rc = GstCntlProcessRequestWait(pRequest); 1921 if (RT_SUCCESS(rc)) 1999 Assert(cbWritten); 2000 if (!fAsync) 2001 { 2002 VBoxServiceVerbose(3, "[PID %RU32]: Waiting for response on pRequest=%p, enmType=%u, pvData=0x%p, cbData=%u\n", 2003 pProcess->uPID, pRequest, pRequest->enmType, pRequest->pvData, pRequest->cbData); 2004 2005 rc = gstcntlProcessUnlock(pProcess); 2006 if (RT_SUCCESS(rc)) 2007 rcWait = GstCntlProcessRequestWait(pRequest); 2008 2009 /* NULL current request in any case. */ 1922 2010 pProcess->pRequest = NULL; 2011 } 1923 2012 } 2013 2014 if ( RT_FAILURE(rc) 2015 || fAsync) 2016 { 2017 int rc2 = gstcntlProcessUnlock(pProcess); 2018 AssertRC(rc2); 2019 } 2020 2021 if (RT_SUCCESS(rc)) 2022 rc = rcWait; 1924 2023 } 1925 2024 } -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp
r45604 r45697 553 553 &startupInfo.uFlags, 554 554 /* Arguments */ 555 startupInfo.szArgs, sizeof(startupInfo.szArgs), &startupInfo.uNumArgs,555 startupInfo.szArgs, sizeof(startupInfo.szArgs), &startupInfo.uNumArgs, 556 556 /* Environment */ 557 startupInfo.szEnv, &startupInfo.cbEnv,&startupInfo.uNumEnvVars,557 startupInfo.szEnv, &startupInfo.cbEnv, &startupInfo.uNumEnvVars, 558 558 /* Credentials; for hosts with VBox < 4.3 (protocol version 1). 559 559 * For protocl v2 and up the credentials are part of the session … … 601 601 rc, pHostCtx->uProtocol, pHostCtx->uNumParms); 602 602 603 /* 604 * Note: The context ID can be 0 because we mabye weren't able to fetch the command 605 * from the host. The host in case has to deal with that! 606 */ 607 int rc2 = VbglR3GuestCtrlProcCbStatus(pHostCtx, 0 /* PID, invalid */, 608 PROC_STS_ERROR, rc, 609 NULL /* pvData */, 0 /* cbData */); 610 if (RT_FAILURE(rc2)) 611 { 612 VBoxServiceError("Error sending start process status to host, rc=%Rrc\n", rc2); 613 if (RT_SUCCESS(rc)) 614 rc = rc2; 603 /* Don't report back if we didn't supply sufficient buffer for getting 604 * the actual command -- we don't have the matching context ID. */ 605 if (rc != VERR_TOO_MUCH_DATA) 606 { 607 /* 608 * Note: The context ID can be 0 because we mabye weren't able to fetch the command 609 * from the host. The host in case has to deal with that! 610 */ 611 int rc2 = VbglR3GuestCtrlProcCbStatus(pHostCtx, 0 /* PID, invalid */, 612 PROC_STS_ERROR, rc, 613 NULL /* pvData */, 0 /* cbData */); 614 if (RT_FAILURE(rc2)) 615 VBoxServiceError("Error sending start process status to host, rc=%Rrc\n", rc2); 615 616 } 616 617 } … … 881 882 int rc = VINF_SUCCESS; 882 883 883 /* Only anonymous sessions (that is, sessions which run with local 884 /** @todo Implement asynchronous handling of all commands to speed up overall 885 * performance for handling multiple guest processes at once. At the moment 886 * only one guest process at a time can and will be served. */ 887 888 /** 889 * Only anonymous sessions (that is, sessions which run with local 884 890 * service privileges) or forked session processes can do certain 885 * operations. */ 891 * operations. 892 */ 886 893 bool fImpersonated = ( pSession->uFlags & VBOXSERVICECTRLSESSION_FLAG_FORK 887 894 || pSession->uFlags & VBOXSERVICECTRLSESSION_FLAG_ANONYMOUS); … … 1255 1262 1256 1263 /** 1257 * Finds a (formerly) started guest process given by its PID and locks it.1258 * Must be unlocked by the caller with GstCntlProcessRelease().1264 * Finds a (formerly) started guest process given by its PID and increses 1265 * its reference count. Must be decreased by the caller with GstCntlProcessRelease(). 1259 1266 * 1260 1267 * @return PVBOXSERVICECTRLTHREAD Locked guest process if found, otherwise NULL. … … 1277 1284 rc = RTCritSectEnter(&pCurProcess->CritSect); 1278 1285 if (RT_SUCCESS(rc)) 1286 { 1287 pCurProcess->cRefs++; 1288 rc = RTCritSectLeave(&pCurProcess->CritSect); 1289 AssertRC(rc); 1290 } 1291 1292 if (RT_SUCCESS(rc)) 1279 1293 pProcess = pCurProcess; 1280 1294 break; … … 1282 1296 } 1283 1297 1284 int rc2 = RTCritSectLeave(&pSession->CritSect); 1285 if (RT_SUCCESS(rc)) 1286 rc = rc2; 1298 rc = RTCritSectLeave(&pSession->CritSect); 1299 AssertRC(rc); 1287 1300 } 1288 1301 -
trunk/src/VBox/HostServices/GuestControl/service.cpp
r45482 r45697 332 332 rc = VERR_INVALID_PARAMETER; 333 333 334 if (paDstParms[i].u.pointer.size < mpParms[i].u.pointer.size) 334 if ( RT_SUCCESS(rc) 335 && paDstParms[i].u.pointer.size < mpParms[i].u.pointer.size) 335 336 rc = VERR_BUFFER_OVERFLOW; 336 337 … … 525 526 mHostCmdRc = VINF_SUCCESS; 526 527 mHostCmdTries = 0; 528 mPeekCount = 0; 527 529 528 530 return nextItem; … … 630 632 int rc = VINF_SUCCESS; 631 633 632 LogFlowFunc(("[Client %RU32] pConnection=%p, mHostCmdRc=%Rrc, mHostCmdTries=%RU32 \n",633 mID, pConnection, mHostCmdRc, mHostCmdTries ));634 LogFlowFunc(("[Client %RU32] pConnection=%p, mHostCmdRc=%Rrc, mHostCmdTries=%RU32, mPeekCount=%RU32\n", 635 mID, pConnection, mHostCmdRc, mHostCmdTries, mPeekCount)); 634 636 635 637 mHostCmdRc = SendReply(pConnection, pHostCmd); … … 644 646 /* 645 647 * If the client understood the message but supplied too little buffer space 646 * don't send this message again and drop it after 3 unsuccessful attempts. 647 * The host then should take care of next actions (maybe retry it with a smaller buffer). 648 * don't send this message again and drop it after 6 unsuccessful attempts. 649 * 650 * Note: Due to legacy reasons this the retry counter has to be even because on 651 * every peek there will be the actual command retrieval from the client side. 652 * To not get the actual command if the client actually only wants to peek for 653 * the next command, there needs to be two rounds per try, e.g. 3 rounds = 6 tries. 654 * 655 ** @todo Fix the mess stated above. GUEST_MSG_WAIT should be become GUEST_MSG_PEEK, *only* 656 * (and every time) returning the next upcoming host command (if any, blocking). Then 657 * it's up to the client what to do next, either peeking again or getting the actual 658 * host command via an own GUEST_ type message. 648 659 */ 649 660 if (mHostCmdRc == VERR_TOO_MUCH_DATA) 650 661 { 651 if (mHostCmdTries >= 3)662 if (mHostCmdTries == 6) 652 663 fRemove = true; 653 664 } … … 777 788 else 778 789 { 790 /* If this is the very first peek, make sure to *always* give back the peeking answer 791 * instead of the actual command, even if this command would fit into the current 792 * connection buffer. */ 779 793 if (!mPeekCount) 780 794 { -
trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp
r45482 r45697 736 736 737 737 com::SafeArray<BYTE> data((size_t)dataCb.cbData); 738 data.initFrom((BYTE*)dataCb.pvData, dataCb.cbData); 738 if (dataCb.cbData) 739 data.initFrom((BYTE*)dataCb.pvData, dataCb.cbData); 739 740 740 741 fireGuestProcessOutputEvent(mEventSource, mSession, this, … … 755 756 /* pcbRead is optional. */ 756 757 757 /** @todo Validate uHandle. */758 759 758 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 760 759 761 if (mData.mStatus != ProcessStatus_Started) 760 if ( mData.mStatus != ProcessStatus_Started 761 /* Skip reading if the process wasn't started with the appropriate 762 * flags. */ 763 || ( ( uHandle == OUTPUT_HANDLE_ID_STDOUT 764 || uHandle == OUTPUT_HANDLE_ID_STDOUT_DEPRECATED) 765 && !(mData.mProcess.mFlags & ProcessCreateFlag_WaitForStdOut)) 766 || ( uHandle == OUTPUT_HANDLE_ID_STDERR 767 && !(mData.mProcess.mFlags & ProcessCreateFlag_WaitForStdErr)) 768 ) 762 769 { 763 770 if (pcbRead) … … 780 787 paParms[i++].setUInt32(0 /* Flags, none set yet. */); 781 788 789 alock.release(); /* Drop the write lock before sending. */ 790 782 791 vrc = sendCommand(HOST_EXEC_GET_OUTPUT, i, paParms); 783 792 } 784 793 785 794 if (RT_SUCCESS(vrc)) 786 {787 alock.release(); /* Drop the write lock before waiting. */788 789 795 vrc = waitForOutput(uHandle, uTimeoutMS, 790 796 pvData, cbData, pcbRead); 791 }792 797 793 798 LogFlowFuncLeaveRC(vrc); … … 904 909 if (RT_SUCCESS(vrc)) 905 910 vrc = mData.mProcess.mEnvironment.BuildEnvironmentBlock(&pvEnv, &cbEnv, NULL /* cEnv */); 911 912 uint32_t uTimeoutMS = mData.mProcess.mTimeoutMS; 906 913 907 914 if (RT_SUCCESS(vrc)) … … 939 946 paParms[i++].setUInt32(UINT32_MAX /* Infinite timeout */); 940 947 else 941 paParms[i++].setUInt32( mData.mProcess.mTimeoutMS);948 paParms[i++].setUInt32(uTimeoutMS); 942 949 if (uProtocol >= 2) 943 950 { … … 950 957 } 951 958 959 alock.release(); /* Drop the write lock before sending. */ 960 952 961 /* Note: Don't hold the write lock in here. */ 953 962 vrc = sendCommand(HOST_EXEC_CMD, i, paParms); … … 963 972 RTStrFree(pszArgs); 964 973 965 uint32_t uTimeoutMS = mData.mProcess.mTimeoutMS;966 967 /* Drop the write lock again before waiting. */968 alock.release();969 970 974 if (RT_SUCCESS(vrc)) 971 975 { 972 vrc = waitForStatusChange(ProcessWaitForFlag_Start, 30 * 1000 /* Timeout */,976 vrc = waitForStatusChange(ProcessWaitForFlag_Start, uTimeoutMS, 973 977 NULL /* Process status */, pGuestRc); 974 978 } … … 1055 1059 paParms[i++].setUInt32(mData.mPID); 1056 1060 1061 alock.release(); /* Drop the write lock before sending. */ 1062 1057 1063 vrc = sendCommand(HOST_EXEC_TERMINATE, i, paParms); 1058 1064 } 1059 1065 1060 1066 if (RT_SUCCESS(vrc)) 1061 {1062 alock.release(); /* Drop the write lock before waiting. */1063 1064 1067 vrc = waitForStatusChange(ProcessWaitForFlag_Terminate, 1065 1068 30 * 1000 /* 30s timeout */, 1066 1069 NULL /* ProcessStatus */, pGuestRc); 1067 }1068 1069 1070 LogFlowFuncLeaveRC(vrc); 1070 1071 return vrc; … … 1267 1268 if (SUCCEEDED(hr)) 1268 1269 { 1269 LogFlowThisFunc(("Waiting for guest fileevent(s) (timeout=%RU32ms, %zu events) ...\n",1270 LogFlowThisFunc(("Waiting for guest process event(s) (timeout=%RU32ms, %zu events) ...\n", 1270 1271 uTimeoutMS, arrEventTypes.size())); 1271 1272 … … 1427 1428 ComAssertComRC(hr); 1428 1429 size_t cbRead = data.size(); 1429 if ( cbRead 1430 && cbRead <= cbData) 1430 if (cbRead) 1431 1431 { 1432 memcpy(pvData, data.raw(), data.size()); 1432 if (cbRead <= cbData) 1433 { 1434 /* Copy data from event into our buffer. */ 1435 memcpy(pvData, data.raw(), data.size()); 1436 } 1437 else 1438 vrc = VERR_BUFFER_OVERFLOW; 1433 1439 } 1434 else1435 vrc = VERR_BUFFER_OVERFLOW;1436 1440 } 1437 1441 if (pcbRead) 1438 1442 { 1439 hr = pProcessEvent->COMGETTER(Processed)((ULONG*)pcbRead); 1443 ULONG cbRead; 1444 hr = pProcessEvent->COMGETTER(Processed)(&cbRead); 1440 1445 ComAssertComRC(hr); 1446 *pcbRead = (uint32_t)cbRead; 1441 1447 } 1442 1448 … … 1525 1531 paParms[i++].setUInt32(cbData); 1526 1532 1533 alock.release(); /* Drop the write lock before sending. */ 1534 1527 1535 vrc = sendCommand(HOST_EXEC_SET_INPUT, i, paParms); 1528 1536 } … … 1530 1538 if (RT_SUCCESS(vrc)) 1531 1539 { 1532 alock.release(); /* Drop the write lock before waiting. */1533 1534 1540 ProcessInputStatus_T inputStatus; 1535 1541 uint32_t cbProcessed; … … 1593 1599 } 1594 1600 1595 LogFlowThisFunc(("rc=%Rrc, cbRead=%RU 64\n", vrc, cbRead));1601 LogFlowThisFunc(("rc=%Rrc, cbRead=%RU32\n", vrc, cbRead)); 1596 1602 1597 1603 LogFlowFuncLeaveRC(vrc); … … 1736 1742 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1737 1743 1744 com::SafeArray<BYTE> data(ComSafeArrayInArg(aData)); 1745 1738 1746 HRESULT hr = S_OK; 1739 1747 1740 com::SafeArray<BYTE> data(ComSafeArrayInArg(aData)); int guestRc;1741 int vrc = writeData(aHandle, aFlags, data.raw(), data.size(), aTimeoutMS, (uint32_t*)aWritten, &guestRc);1748 uint32_t cbWritten; int guestRc; 1749 int vrc = writeData(aHandle, aFlags, data.raw(), data.size(), aTimeoutMS, &cbWritten, &guestRc); 1742 1750 if (RT_FAILURE(vrc)) 1743 1751 { … … 1756 1764 } 1757 1765 1758 LogFlowThisFunc(("rc=%Rrc, aWritten=%RU32\n", vrc, aWritten)); 1766 LogFlowThisFunc(("rc=%Rrc, aWritten=%RU32\n", vrc, cbWritten)); 1767 1768 *aWritten = (ULONG)cbWritten; 1759 1769 1760 1770 LogFlowFuncLeaveRC(vrc); -
trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp
r45434 r45697 1358 1358 pCurProc->getObjectID(), mData.mSession.mID, uPID, mData.mProcesses.size() - 1, mData.mNumObjects - 1)); 1359 1359 1360 LogFlowFunc(("1\n"));1361 1360 mData.mProcesses.erase(itProcs); 1362 1361 mData.mNumObjects--; 1363 1362 1364 LogFlowFunc(("2\n"));1365 1363 fireGuestProcessRegisteredEvent(mEventSource, this /* Session */, NULL /* Process */, 1366 1364 uPID, false /* Process unregistered */); 1367 LogFlowFunc(("3\n"));1368 1365 rc = VINF_SUCCESS; 1369 1366 break; 1370 1367 } 1371 1368 1372 LogFlowFunc(("4\n"));1373 1369 itProcs++; 1374 1370 }
Note:
See TracChangeset
for help on using the changeset viewer.