Changeset 39843 in vbox for trunk/src/VBox/Additions/common
- Timestamp:
- Jan 23, 2012 6:38:18 PM (13 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp
r39202 r39843 40 40 #include <iprt/buildconfig.h> 41 41 #include <iprt/initterm.h> 42 #ifdef DEBUG 43 # include <iprt/memtracker.h> 44 #endif 42 45 #include <iprt/message.h> 43 46 #include <iprt/path.h> … … 935 938 #ifdef DEBUG 936 939 RTCritSectDelete(&g_csLog); 940 //RTMemTrackerDumpAllToStdOut(); 937 941 #endif 938 942 return rcExit; -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
r39659 r39843 187 187 } 188 188 else if (RT_FAILURE(rc)) 189 VBoxServiceVerbose(3, "Control: Getting host message failed with %Rrc\n", rc); /* VERR_GEN_IO_FAILURE seems to be normal if ran 189 VBoxServiceVerbose(3, "Control: Getting host message failed with %Rrc\n", rc); /* VERR_GEN_IO_FAILURE seems to be normal if ran into timeout. */ 190 190 if (RT_SUCCESS(rc)) 191 191 { … … 360 360 361 361 int rc = VINF_SUCCESS; 362 363 VBOXSERVICECTRLREQUEST ctrlRequest; 364 ctrlRequest.uCID = uCID; 365 ctrlRequest.cbData = cbBuf; 366 ctrlRequest.pvData = (uint8_t*)pvBuf; 367 362 VBOXSERVICECTRLREQUESTTYPE reqType; 368 363 switch (uHandleId) 369 364 { 370 365 case OUTPUT_HANDLE_ID_STDERR: 371 ctrlRequest.enmType = VBOXSERVICECTRLREQUEST_STDERR_READ;366 reqType = VBOXSERVICECTRLREQUEST_STDERR_READ; 372 367 break; 373 368 374 369 case OUTPUT_HANDLE_ID_STDOUT: 375 370 case OUTPUT_HANDLE_ID_STDOUT_DEPRECATED: 376 ctrlRequest.enmType = VBOXSERVICECTRLREQUEST_STDOUT_READ;371 reqType = VBOXSERVICECTRLREQUEST_STDOUT_READ; 377 372 break; 378 373 … … 382 377 } 383 378 379 PVBOXSERVICECTRLREQUEST pRequest; 384 380 if (RT_SUCCESS(rc)) 385 rc = VBoxServiceControlThreadPerform(uPID, &ctrlRequest); 386 387 if (RT_SUCCESS(rc)) 388 { 389 if (pcbRead) 390 *pcbRead = ctrlRequest.cbData; 391 } 392 else /* Something went wrong, nothing read. */ 393 *pcbRead = 0; 381 { 382 rc = VBoxServiceControlThreadRequestAllocEx(&pRequest, reqType, 383 pvBuf, cbBuf, uCID); 384 if (RT_SUCCESS(rc)) 385 rc = VBoxServiceControlThreadPerform(uPID, pRequest); 386 387 if (RT_SUCCESS(rc)) 388 { 389 if (pcbRead) 390 *pcbRead = pRequest->cbData; 391 } 392 393 VBoxServiceControlThreadRequestFree(pRequest); 394 } 394 395 395 396 return rc; … … 416 417 /* pcbWritten is optional. */ 417 418 418 int rc = VINF_SUCCESS; 419 420 VBOXSERVICECTRLREQUEST ctrlRequest; 421 ctrlRequest.uCID = uCID; 422 ctrlRequest.cbData = cbBuf; 423 ctrlRequest.pvData = pvBuf; 424 ctrlRequest.enmType = fPendingClose 425 ? VBOXSERVICECTRLREQUEST_STDIN_WRITE_EOF : VBOXSERVICECTRLREQUEST_STDIN_WRITE; 419 PVBOXSERVICECTRLREQUEST pRequest; 420 int rc = VBoxServiceControlThreadRequestAllocEx(&pRequest, 421 fPendingClose 422 ? VBOXSERVICECTRLREQUEST_STDIN_WRITE_EOF 423 : VBOXSERVICECTRLREQUEST_STDIN_WRITE, 424 pvBuf, cbBuf, uCID); 426 425 if (RT_SUCCESS(rc)) 427 rc = VBoxServiceControlThreadPerform(uPID, &ctrlRequest); 428 429 if (RT_SUCCESS(rc)) 430 { 431 if (pcbWritten) 432 *pcbWritten = ctrlRequest.cbData; 426 { 427 rc = VBoxServiceControlThreadPerform(uPID, pRequest); 428 if (RT_SUCCESS(rc)) 429 { 430 if (pcbWritten) 431 *pcbWritten = pRequest->cbData; 432 } 433 434 VBoxServiceControlThreadRequestFree(pRequest); 433 435 } 434 436 … … 559 561 if (RT_SUCCESS(rc)) 560 562 { 561 uint32_t cbRead = 0;562 563 uint8_t *pBuf = (uint8_t*)RTMemAlloc(_64K); 563 564 if (pBuf) 564 565 { 566 uint32_t cbRead = 0; 565 567 rc = VBoxServiceControlExecGetOutput(uPID, uContextID, uHandleID, RT_INDEFINITE_WAIT /* Timeout */, 566 568 pBuf, _64K /* cbSize */, &cbRead); 569 VBoxServiceVerbose(3, "Control: Got output returned with rc=%Rrc (PID=%u, CID=%u, cbRead=%u, uHandle=%u, uFlags=%u)\n", 570 rc, uPID, uContextID, cbRead, uHandleID, uFlags); 567 571 568 572 /** Note: Don't convert/touch/modify/whatever the output data here! This might be binary 569 573 * data which the host needs to work with -- so just pass through all data unfiltered! */ 570 574 571 if (RT_SUCCESS(rc))572 VBoxServiceVerbose(2, "Control: Got output, PID=%u, CID=%u, cbRead=%u, uHandle=%u, uFlags=%u\n",573 uPID, uContextID, cbRead, uHandleID, uFlags);574 else if (rc == VERR_NOT_FOUND)575 VBoxServiceVerbose(2, "Control: PID=%u not found, CID=%u, uHandle=%u\n",576 uPID, uContextID, uHandleID, rc);577 else578 VBoxServiceError("Control: Failed to retrieve output for PID=%u, CID=%u, uHandle=%u, rc=%Rrc\n",579 uPID, uContextID, uHandleID, rc);580 575 /* Note: Since the context ID is unique the request *has* to be completed here, 581 576 * regardless whether we got data or not! Otherwise the progress object 582 577 * on the host never will get completed! */ 583 /* cbRead now contains actual size. */584 578 int rc2 = VbglR3GuestCtrlExecSendOut(idClient, uContextID, uPID, uHandleID, uFlags, 585 579 pBuf, cbRead); … … 656 650 657 651 #ifdef DEBUG 658 659 660 661 662 652 PVBOXSERVICECTRLTHREAD pThreadCur; 653 uint32_t cThreads = 0; 654 RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node) 655 cThreads++; 656 VBoxServiceVerbose(4, "Control: Guest process threads left=%u\n", cThreads); 663 657 #endif 664 658 AssertMsg(RTListIsEmpty(&g_GuestControlThreads), … … 717 711 RTListForEach(&g_GuestControlThreads, pThread, VBOXSERVICECTRLTHREAD, Node) 718 712 { 719 VBOXSERVICECTRLTHREADSTATUS enmStatus = VBoxServiceControlThreadGetStatus(pThread); 720 if (enmStatus == VBOXSERVICECTRLTHREADSTATUS_STARTED) 721 uProcsRunning++; 722 else if (enmStatus == VBOXSERVICECTRLTHREADSTATUS_STOPPED) 723 uProcsStopped++; 724 else 725 AssertMsgFailed(("Control: Guest process neither started nor stopped!?\n")); 713 VBoxServiceControlThreadActive(pThread) 714 ? uProcsRunning++ 715 : uProcsStopped++; 726 716 } 727 717 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp
r39462 r39843 44 44 /* Internal functions. */ 45 45 static int vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread); 46 static int vboxServiceControlThreadRequestCancel(PVBOXSERVICECTRLREQUEST pThread); 46 47 47 48 /** … … 70 71 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS) 71 72 { 72 AssertPtr (pThread);73 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 73 74 74 75 /* General stuff. */ … … 89 90 return rc; 90 91 91 rc = RTSemEventMultiCreate(&pThread->RequestEvent);92 AssertRCReturn(rc, rc);93 94 92 pThread->uPID = 0; /* Don't have a PID yet. */ 95 pThread->pszCmd = RTStrDup(pszCmd);96 93 pThread->uFlags = uFlags; 97 94 pThread->uTimeLimitMS = ( uTimeLimitMS == UINT32_MAX … … 136 133 cbLen += cbStr + 1; /* Skip terminating '\0' */ 137 134 } 138 } 135 Assert(i == pThread->uNumEnvVars); 136 } 137 138 /* The actual command to execute. */ 139 pThread->pszCmd = RTStrDup(pszCmd); 140 AssertPtr(pThread->pszCmd); 139 141 140 142 /* User management. */ … … 161 163 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 162 164 163 VBoxServiceVerbose( 1, "ControlThread: [PID %u]: Shutting down...\n",165 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Freeing thread data ...\n", 164 166 pThread->uPID); 165 167 166 /* Signal the request event to unblock potential waiters. */ 167 int rc = RTSemEventMultiSignal(pThread->RequestEvent); 168 int rc = vboxServiceControlThreadRequestCancel(pThread->pRequest); 168 169 if (RT_FAILURE(rc)) 169 170 VBoxServiceError("ControlThread: [PID %u]: Signalling request event failed, rc=%Rrc\n", 170 171 pThread->uPID, rc); 171 172 172 173 rc = RTCritSectEnter(&pThread->CritSect); 173 174 if (RT_SUCCESS(rc)) 174 175 { 175 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Freeing thread data ...\n",176 pThread->uPID);177 178 RTStrFree(pThread->pszCmd);179 176 if (pThread->uNumEnvVars) 180 177 { … … 184 181 } 185 182 RTGetOptArgvFree(pThread->papszArgs); 183 184 RTStrFree(pThread->pszCmd); 186 185 RTStrFree(pThread->pszUser); 187 186 RTStrFree(pThread->pszPassword); 188 187 189 rc = RTSemEventMultiDestroy(pThread->RequestEvent); 190 AssertRC(rc); 191 192 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Cleaning up ...\n", 188 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Setting stopped state\n", 193 189 pThread->uPID); 194 190 … … 233 229 * The guest thread loop will do that as soon as it processes the quit message. */ 234 230 235 VBOXSERVICECTRLREQUEST ctrlRequest; 236 RT_ZERO(ctrlRequest); 237 ctrlRequest.enmType = VBOXSERVICECTRLREQUEST_QUIT; 238 239 int rc = VBoxServiceControlThreadPerform(pThread->uPID, &ctrlRequest); 240 if (RT_FAILURE(rc)) 241 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Sending quit request failed with rc=%Rrc\n", 242 pThread->uPID, rc); 231 PVBOXSERVICECTRLREQUEST pRequest; 232 int rc = VBoxServiceControlThreadRequestAlloc(&pRequest, VBOXSERVICECTRLREQUEST_QUIT); 233 if (RT_SUCCESS(rc)) 234 { 235 rc = VBoxServiceControlThreadPerform(pThread->uPID, pRequest); 236 if (RT_FAILURE(rc)) 237 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Sending quit request failed with rc=%Rrc\n", 238 pThread->uPID, rc); 239 240 VBoxServiceControlThreadRequestFree(pRequest); 241 } 243 242 return rc; 244 243 } … … 266 265 int rcThread; 267 266 rc = RTThreadWait(pThread->Thread, msTimeout, &rcThread); 268 if (RT_FAILURE(rcThread)) 269 { 270 VBoxServiceError("ControlThread: [PID %u]: Shutdown returned error rc=%Rrc\n", 271 pThread->uPID, rcThread); 272 if (RT_SUCCESS(rc)) 267 if (RT_FAILURE(rc)) 268 { 269 VBoxServiceError("ControlThread: [PID %u]: Waiting for shutting down thread returned error rc=%Rrc\n", 270 pThread->uPID, rc); 271 } 272 else 273 { 274 if (RT_FAILURE(rcThread)) 275 { 276 VBoxServiceError("ControlThread: [PID %u]: Shutdown returned error rc=%Rrc\n", 277 pThread->uPID, rcThread); 273 278 rc = rcThread; 279 } 274 280 } 275 281 } … … 279 285 280 286 /** 281 * Returns the guest process thread's current status.282 * 283 * @return VBOXSERVICECTRLTHREADSTATUS287 * Returns whether a guest process thread still is up and running. 288 * 289 * @return true if thread is running, false if not. 284 290 * @param pThread Thread to determine current status for. 285 291 */ 286 VBOXSERVICECTRLTHREADSTATUS VBoxServiceControlThreadGetStatus(const PVBOXSERVICECTRLTHREAD pThread)287 { 288 AssertPtrReturn(pThread, VBOXSERVICECTRLTHREADSTATUS_UNKNOWN);292 bool VBoxServiceControlThreadActive(const PVBOXSERVICECTRLTHREAD pThread) 293 { 294 AssertPtrReturn(pThread, false); 289 295 290 296 int rc = RTCritSectEnter(&pThread->CritSect); 291 297 if (RT_SUCCESS(rc)) 292 298 { 293 Assert(pThread->fStarted != pThread->fStopped); 294 295 VBOXSERVICECTRLTHREADSTATUS enmStatus = VBOXSERVICECTRLTHREADSTATUS_UNKNOWN; 296 /** @todo Add more logic here. */ 297 /** @todo Remove fStarted/fStopped and just use this VBOXSERVICECTRLTHREADSTATUS. */ 298 if (pThread->fStarted) 299 enmStatus = VBOXSERVICECTRLTHREADSTATUS_STARTED; 300 else if (pThread->fStopped) 301 enmStatus = VBOXSERVICECTRLTHREADSTATUS_STOPPED; 302 else 303 AssertMsgFailed(("ControlThread: Uknown thread status (0x%x)\n")); 299 /* We only are interested whether the thread really is alive 300 * and kicking or not, meaning: 301 * - thread was started 302 * - thread is able to serve IPC messages 303 * 304 * Even if the fShutdown flag is set this means the thread should be 305 * considered as being running (destruction phase). 306 */ 307 bool fRunning = !pThread->fStopped; 304 308 305 309 rc = RTCritSectLeave(&pThread->CritSect); 306 310 AssertRC(rc); 307 311 308 return enmStatus;309 } 310 311 return VBOXSERVICECTRLTHREADSTATUS_UNKNOWN;312 return fRunning; 313 } 314 315 return false; 312 316 } 313 317 … … 368 372 PRTPIPE phPipeR, uint32_t idPollHnd) 369 373 { 370 int rc = VINF_SUCCESS; 371 372 rc = RTPollSetRemove(hPollSet, idPollHnd); 373 AssertRC(rc); 374 375 rc = RTPipeClose(*phPipeR); 376 AssertRC(rc); 377 *phPipeR = NIL_RTPIPE; 378 379 return rc; 374 AssertPtrReturn(phPipeR, VERR_INVALID_POINTER); 375 376 #ifdef DEBUG 377 VBoxServiceVerbose(4, "ControlThread: VBoxServiceControlThreadHandleOutputError: fPollEvt=0x%x, idPollHnd=%u\n", 378 fPollEvt, idPollHnd); 379 #endif 380 381 /* Remove pipe from poll set. */ 382 int rc2 = RTPollSetRemove(hPollSet, idPollHnd); 383 AssertMsg(RT_SUCCESS(rc2) || rc2 == VERR_POLL_HANDLE_ID_NOT_FOUND, ("%Rrc\n", rc2)); 384 385 bool fClosePipe = true; /* By default close the pipe. */ 386 387 /* Check if there's remaining data to read from the pipe. */ 388 size_t cbReadable; 389 rc2 = RTPipeQueryReadable(*phPipeR, &cbReadable); 390 if ( RT_SUCCESS(rc2) 391 && cbReadable) 392 { 393 VBoxServiceVerbose(3, "ControlThread: VBoxServiceControlThreadHandleOutputError: idPollHnd=%u has %ld bytes left, vetoing close\n", 394 idPollHnd, cbReadable); 395 396 /* Veto closing the pipe yet because there's still stuff to read 397 * from the pipe. This can happen on UNIX-y systems where on 398 * error/hangup there still can be data to be read out. */ 399 fClosePipe = false; 400 } 401 else 402 VBoxServiceVerbose(3, "ControlThread: VBoxServiceControlThreadHandleOutputError: idPollHnd=%u will be closed\n", 403 idPollHnd); 404 405 if ( *phPipeR != NIL_RTPIPE 406 && fClosePipe) 407 { 408 rc2 = RTPipeClose(*phPipeR); 409 AssertRC(rc2); 410 *phPipeR = NIL_RTPIPE; 411 } 412 413 return VINF_SUCCESS; 380 414 } 381 415 … … 394 428 PRTPIPE phPipeR, uint32_t idPollHnd) 395 429 { 430 #if 0 431 VBoxServiceVerbose(4, "ControlThread: VBoxServiceControlThreadHandleOutputEvent: fPollEvt=0x%x, idPollHnd=%u\n", 432 fPollEvt, idPollHnd); 433 #endif 434 396 435 int rc = VINF_SUCCESS; 397 436 398 if (fPollEvt & RTPOLL_EVT_READ) 399 { 437 #ifdef DEBUG 438 size_t cbReadable; 439 rc = RTPipeQueryReadable(*phPipeR, &cbReadable); 440 if ( RT_SUCCESS(rc) 441 && cbReadable) 442 { 443 VBoxServiceVerbose(4, "ControlThread: VBoxServiceControlThreadHandleOutputEvent: cbReadable=%ld\n", 444 cbReadable); 445 } 446 #endif 447 448 #if 0 449 //if (fPollEvt & RTPOLL_EVT_READ) 450 { 451 size_t cbRead = 0; 452 uint8_t byData[_64K]; 453 rc = RTPipeRead(*phPipeR, 454 byData, sizeof(byData), &cbRead); 455 VBoxServiceVerbose(4, "ControlThread: VBoxServiceControlThreadHandleOutputEvent cbRead=%u, rc=%Rrc\n", 456 cbRead, rc); 400 457 401 458 /* Make sure we go another poll round in case there was too much data … … 403 460 fPollEvt &= RTPOLL_EVT_ERROR; 404 461 } 462 #endif 405 463 406 464 if (fPollEvt & RTPOLL_EVT_ERROR) … … 415 473 PVBOXSERVICECTRLTHREAD pThread) 416 474 { 417 #ifdef DEBUG_andy418 VBoxServiceVerbose(4, "ControlThread: HandleIPCRequest\n");419 #endif420 421 475 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 422 476 AssertPtrReturn(phStdInW, VERR_INVALID_POINTER); … … 446 500 /** @todo Check for some conditions to check to 447 501 * veto quitting. */ 448 pThread->fShutdown = true;449 rcReq = V INF_SUCCESS;502 ASMAtomicXchgBool(&pThread->fShutdown, true); 503 rcReq = VERR_CANCELLED; 450 504 break; 451 505 } … … 498 552 rcReq = RTPipeRead(*pPipeR, 499 553 pRequest->pvData, pRequest->cbData, &cbRead); 500 if (rcReq == VERR_BROKEN_PIPE) 501 rcReq = VINF_EOF; 554 if (RT_FAILURE(rcReq)) 555 { 556 RTPollSetRemove(hPollSet, pRequest->enmType == VBOXSERVICECTRLREQUEST_STDERR_READ 557 ? VBOXSERVICECTRLPIPEID_STDERR : VBOXSERVICECTRLPIPEID_STDOUT); 558 RTPipeClose(*pPipeR); 559 *pPipeR = NIL_RTPIPE; 560 if (rcReq == VERR_BROKEN_PIPE) 561 rcReq = VINF_EOF; 562 } 502 563 } 503 564 else … … 518 579 ? rcReq : rc; 519 580 520 VBoxServiceVerbose(2, "ControlThread: [PID %u]: Handled req=%u, CID=%u, rc Req=%Rrc, cbData=%u\n",521 pThread->uPID, pRequest->enmType, pRequest->uCID, rcReq, pRequest->cbData);581 VBoxServiceVerbose(2, "ControlThread: [PID %u]: Handled req=%u, CID=%u, rc=%Rrc, cbData=%u\n", 582 pThread->uPID, pRequest->enmType, pRequest->uCID, pRequest->rc, pRequest->cbData); 522 583 523 584 /* In any case, regardless of the result, we notify 524 585 * the main guest control to unblock it. */ 525 int rc2 = RTSemEventMultiSignal(p Thread->RequestEvent);586 int rc2 = RTSemEventMultiSignal(pRequest->Event); 526 587 AssertRC(rc2); 588 527 589 /* No access to pRequest here anymore -- could be out of scope 528 590 * or modified already! */ 591 pThread->pRequest = pRequest = NULL; 529 592 530 593 return rc; … … 640 703 } 641 704 705 #if 0 706 VBoxServiceVerbose(4, "ControlThread: [PID %u]: Polling done, pollRC=%Rrc, pollCnt=%u, rc=%Rrc, fShutdown=%RTbool\n", 707 pThread->uPID, rc2, RTPollSetGetCount(hPollSet), rc, pThread->fShutdown); 708 #endif 642 709 /* 643 710 * Check for process death. … … 665 732 666 733 /* 667 * If the process has terminated, we're should head out. 734 * If the process has terminated and all output has been consumed, 735 * we should be heading out. 668 736 */ 669 if (!fProcessAlive) 737 if ( !fProcessAlive 738 && *phStdOutR == NIL_RTPIPE 739 && *phStdErrR == NIL_RTPIPE) 670 740 break; 671 741 … … 700 770 701 771 /* Reset the polling interval since we've done all pending work. */ 702 cMsPollCur = cMilliesLeft >= cMsPollBase ? cMsPollBase : cMilliesLeft; 772 cMsPollCur = fProcessAlive 773 ? cMsPollBase 774 : RT_MS_1MIN; 775 if (cMilliesLeft < cMsPollCur) 776 cMsPollCur = cMilliesLeft; 703 777 704 778 /* … … 707 781 if (pThread->fShutdown) 708 782 break; 783 } 784 785 rc2 = RTCritSectEnter(&pThread->CritSect); 786 if (RT_SUCCESS(rc2)) 787 { 788 ASMAtomicXchgBool(&pThread->fShutdown, true); 789 790 rc2 = RTCritSectLeave(&pThread->CritSect); 791 AssertRC(rc2); 709 792 } 710 793 … … 789 872 else if (ProcessStatus.enmReason == RTPROCEXITREASON_NORMAL) 790 873 { 791 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_NORMAL ( %u)\n",874 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_NORMAL (Exit code: %u)\n", 792 875 pThread->uPID, ProcessStatus.iStatus); 793 876 … … 797 880 else if (ProcessStatus.enmReason == RTPROCEXITREASON_SIGNAL) 798 881 { 799 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_SIGNAL ( %u)\n",882 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_SIGNAL (Signal: %u)\n", 800 883 pThread->uPID, ProcessStatus.iStatus); 801 884 … … 805 888 else if (ProcessStatus.enmReason == RTPROCEXITREASON_ABEND) 806 889 { 807 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_ABEND (%u)\n", 808 pThread->uPID, ProcessStatus.iStatus); 890 /* ProcessStatus.iStatus will be undefined. */ 891 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_ABEND\n", 892 pThread->uPID); 809 893 810 894 uStatus = PROC_STS_TEA; … … 834 918 835 919 920 /** 921 * Initializes a pipe's handle and pipe object. 922 * 923 * @return IPRT status code. 924 * @param ph The pipe's handle to initialize. 925 * @param phPipe The pipe's object to initialize. 926 */ 836 927 static int vboxServiceControlThreadInitPipe(PRTHANDLE ph, PRTPIPE phPipe) 837 928 { … … 844 935 845 936 return VINF_SUCCESS; 937 } 938 939 940 /** 941 * Allocates a guest thread request with the specified request data. 942 * 943 * @return IPRT status code. 944 * @param ppReq Pointer that will receive the newly allocated request. 945 * Must be freed later with VBoxServiceControlThreadRequestFree(). 946 * @param enmType Request type. 947 * @param pbData Payload data, based on request type. 948 * @param cbData Size of payload data (in bytes). 949 * @param uCID Context ID to which this request belongs to. 950 */ 951 int VBoxServiceControlThreadRequestAllocEx(PVBOXSERVICECTRLREQUEST *ppReq, 952 VBOXSERVICECTRLREQUESTTYPE enmType, 953 void* pbData, 954 size_t cbData, 955 uint32_t uCID) 956 { 957 AssertPtrReturn(ppReq, VERR_INVALID_POINTER); 958 959 PVBOXSERVICECTRLREQUEST pReq = (PVBOXSERVICECTRLREQUEST) 960 RTMemAlloc(sizeof(VBOXSERVICECTRLREQUEST)); 961 AssertPtrReturn(pReq, VERR_NO_MEMORY); 962 963 RT_ZERO(*pReq); 964 pReq->enmType = enmType; 965 pReq->uCID = uCID; 966 pReq->cbData = cbData; 967 pReq->pvData = (uint8_t*)pbData; 968 969 /* Set request result to some defined state in case 970 * it got cancelled. */ 971 pReq->rc = VERR_CANCELLED; 972 973 int rc = RTSemEventMultiCreate(&pReq->Event); 974 AssertRC(rc); 975 976 if (RT_SUCCESS(rc)) 977 { 978 *ppReq = pReq; 979 return VINF_SUCCESS; 980 } 981 982 RTMemFree(pReq); 983 return rc; 984 } 985 986 987 /** 988 * Allocates a guest thread request with the specified request data. 989 * 990 * @return IPRT status code. 991 * @param ppReq Pointer that will receive the newly allocated request. 992 * Must be freed later with VBoxServiceControlThreadRequestFree(). 993 * @param enmType Request type. 994 */ 995 int VBoxServiceControlThreadRequestAlloc(PVBOXSERVICECTRLREQUEST *ppReq, 996 VBOXSERVICECTRLREQUESTTYPE enmType) 997 { 998 return VBoxServiceControlThreadRequestAllocEx(ppReq, enmType, 999 0 /* cbData */, NULL /* pvData */, 1000 0 /* ContextID */); 1001 } 1002 1003 1004 /** 1005 * Cancels a previously fired off guest thread request. 1006 * 1007 * Note: Does *not* do locking since VBoxServiceControlThreadRequestWait() 1008 * holds the lock (critsect); so only trigger the signal; the owner 1009 * needs to clean up afterwards. 1010 * 1011 * @return IPRT status code. 1012 * @param pReq Request to cancel. 1013 */ 1014 static int vboxServiceControlThreadRequestCancel(PVBOXSERVICECTRLREQUEST pReq) 1015 { 1016 if (!pReq) /* Silently skip non-initialized requests. */ 1017 return VINF_SUCCESS; 1018 1019 VBoxServiceVerbose(4, "ControlThread: Cancelling request 0x%p\n", pReq); 1020 1021 return RTSemEventMultiSignal(pReq->Event); 1022 } 1023 1024 1025 /** 1026 * Frees a formerly allocated guest thread request. 1027 * 1028 * @return IPRT status code. 1029 * @param pReq Request to free. 1030 */ 1031 void VBoxServiceControlThreadRequestFree(PVBOXSERVICECTRLREQUEST pReq) 1032 { 1033 AssertPtrReturnVoid(pReq); 1034 1035 VBoxServiceVerbose(4, "ControlThread: Freeing request 0x%p (event 0x%p)\n", 1036 pReq, &pReq->Event); 1037 1038 int rc = RTSemEventMultiDestroy(pReq->Event); 1039 AssertRC(rc); 1040 1041 RTMemFree(pReq); 1042 pReq = NULL; 1043 } 1044 1045 1046 /** 1047 * Waits for a guest thread's event to get triggered. 1048 * 1049 * @return IPRT status code. 1050 * @param pReq Request to wait for. 1051 */ 1052 int VBoxServiceControlThreadRequestWait(PVBOXSERVICECTRLREQUEST pReq) 1053 { 1054 AssertPtrReturn(pReq, VERR_INVALID_POINTER); 1055 1056 /* Wait on the request to get completed (or we are asked to abort/shutdown). */ 1057 int rc = RTSemEventMultiWait(pReq->Event, RT_INDEFINITE_WAIT); 1058 if (RT_SUCCESS(rc)) 1059 { 1060 VBoxServiceVerbose(4, "ControlThread: Performed request with rc=%Rrc, cbData=%u\n", 1061 pReq->rc, pReq->cbData); 1062 1063 /* Give back overall request result. */ 1064 rc = pReq->rc; 1065 } 1066 else 1067 VBoxServiceError("ControlThread: Waiting for request failed, rc=%Rrc\n", rc); 1068 1069 return rc; 846 1070 } 847 1071 … … 865 1089 { 866 1090 AssertPtrReturn(ph, VERR_INVALID_POINTER); 867 AssertPtrReturn(ph, VERR_INVALID_POINTER);868 1091 AssertPtrReturn(pph, VERR_INVALID_POINTER); 1092 AssertPtrReturn(phPipe, VERR_INVALID_POINTER); 869 1093 870 1094 int rc; … … 914 1138 } 915 1139 else /* Add other piping stuff here. */ 916 rc = V ERR_INVALID_PARAMETER;1140 rc = VINF_SUCCESS; /* Same as parent (us). */ 917 1141 918 1142 return rc; … … 957 1181 * @param cbResolved Size (in bytes) of resolved file name string. 958 1182 */ 959 static int VBoxServiceControlThreadResolveExecutable(const char *pszFileName, char *pszResolved, size_t cbResolved) 1183 static int VBoxServiceControlThreadResolveExecutable(const char *pszFileName, 1184 char *pszResolved, size_t cbResolved) 960 1185 { 961 1186 int rc = VINF_SUCCESS; … … 1020 1245 if (RT_SUCCESS(rc)) 1021 1246 rc = RTStrAAppend(&pszNewArgs, pszArgs); 1247 RTStrFree(pszArgs); 1022 1248 } 1023 1249 } … … 1098 1324 phStdIn, phStdOut, phStdErr, NULL /* pszAsUser */, 1099 1325 NULL /* pszPassword */, phProcess); 1326 RTGetOptArgvFree(papszArgsExp); 1100 1327 } 1101 RTGetOptArgvFree(papszArgsExp);1102 1328 } 1103 1329 return rc; … … 1214 1440 RTHANDLE hStdOut; 1215 1441 PRTHANDLE phStdOut; 1216 RTPIPE hStdOutR;1442 RTPIPE pipeStdOutR; 1217 1443 rc = VBoxServiceControlThreadSetupPipe( (pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDOUT) 1218 1444 ? "|" : "/dev/null", 1219 1445 1 /*STDOUT_FILENO*/, 1220 &hStdOut, &phStdOut, & hStdOutR);1446 &hStdOut, &phStdOut, &pipeStdOutR); 1221 1447 if (RT_SUCCESS(rc)) 1222 1448 { 1223 1449 RTHANDLE hStdErr; 1224 1450 PRTHANDLE phStdErr; 1225 RTPIPE hStdErrR;1451 RTPIPE pipeStdErrR; 1226 1452 rc = VBoxServiceControlThreadSetupPipe( (pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDERR) 1227 1453 ? "|" : "/dev/null", 1228 1454 2 /*STDERR_FILENO*/, 1229 &hStdErr, &phStdErr, & hStdErrR);1455 &hStdErr, &phStdErr, &pipeStdErrR); 1230 1456 if (RT_SUCCESS(rc)) 1231 1457 { … … 1238 1464 if (RT_SUCCESS(rc)) 1239 1465 { 1466 uint32_t uFlags = RTPOLL_EVT_ERROR; 1467 #if 0 1468 /* Add reading event to pollset to get some more information. */ 1469 uFlags |= RTPOLL_EVT_READ; 1470 #endif 1240 1471 /* Stdin. */ 1241 1472 if (RT_SUCCESS(rc)) … … 1243 1474 /* Stdout. */ 1244 1475 if (RT_SUCCESS(rc)) 1245 rc = RTPollSetAddPipe(hPollSet, hStdOutR, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDOUT);1476 rc = RTPollSetAddPipe(hPollSet, pipeStdOutR, uFlags, VBOXSERVICECTRLPIPEID_STDOUT); 1246 1477 /* Stderr. */ 1247 1478 if (RT_SUCCESS(rc)) 1248 rc = RTPollSetAddPipe(hPollSet, hStdErrR, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDERR);1479 rc = RTPollSetAddPipe(hPollSet, pipeStdErrR, uFlags, VBOXSERVICECTRLPIPEID_STDERR); 1249 1480 /* IPC notification pipe. */ 1250 1481 if (RT_SUCCESS(rc)) … … 1269 1500 */ 1270 1501 int rc2 = RTThreadUserSignal(RTThreadSelf()); 1271 if (RT_ FAILURE(rc2))1502 if (RT_SUCCESS(rc)) 1272 1503 rc = rc2; 1273 1504 fSignalled = true; … … 1288 1519 rc = VBoxServiceControlThreadProcLoop(pThread, 1289 1520 hProcess, pThread->uTimeLimitMS, hPollSet, 1290 &pThread->pipeStdInW, & hStdOutR, &hStdErrR);1521 &pThread->pipeStdInW, &pipeStdOutR, &pipeStdErrR); 1291 1522 /* 1292 1523 * The handles that are no longer in the set have … … 1315 1546 pThread->hNotificationPipeW = NIL_RTPIPE; 1316 1547 } 1317 RTPipeClose( hStdErrR);1318 hStdErrR = NIL_RTPIPE;1548 RTPipeClose(pipeStdErrR); 1549 pipeStdErrR = NIL_RTPIPE; 1319 1550 RTHandleClose(phStdErr); 1551 if (phStdErr) 1552 RTHandleClose(phStdErr); 1320 1553 } 1321 RTPipeClose(hStdOutR); 1322 hStdOutR = NIL_RTPIPE; 1323 RTHandleClose(phStdOut); 1554 RTPipeClose(pipeStdOutR); 1555 pipeStdOutR = NIL_RTPIPE; 1556 RTHandleClose(&hStdOut); 1557 if (phStdOut) 1558 RTHandleClose(phStdOut); 1324 1559 } 1325 1560 RTPipeClose(pThread->pipeStdInW); 1561 pThread->pipeStdInW = NIL_RTPIPE; 1326 1562 RTHandleClose(phStdIn); 1327 1563 } … … 1343 1579 } 1344 1580 1345 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Cancelling pending waits (client ID=%u)\n",1581 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Cancelling pending host requests (client ID=%u)\n", 1346 1582 pThread->uPID, pThread->uClientID); 1347 1583 rc2 = VbglR3GuestCtrlCancelPendingWaits(pThread->uClientID); 1348 1584 if (RT_FAILURE(rc2)) 1349 1585 { 1350 VBoxServiceError("ControlThread: [PID %u]: Cancelling pending waits failed; rc=%Rrc\n",1586 VBoxServiceError("ControlThread: [PID %u]: Cancelling pending host requests failed; rc=%Rrc\n", 1351 1587 pThread->uPID, rc2); 1352 1588 if (RT_SUCCESS(rc)) … … 1421 1657 * @param pszPassword Password of specified user name (account). 1422 1658 * @param uTimeLimitMS Time limit (in ms) of the process' life time. 1423 * @param ppNode 1659 * @param ppNode The thread's list node to insert into the global thread list 1424 1660 * on success. 1661 * 1662 ** @todo Put (all?) these parameters into a struct! 1425 1663 */ 1426 1664 int VBoxServiceControlThreadStart(uint32_t uClientID, uint32_t uContextID, … … 1450 1688 { 1451 1689 static uint32_t s_uCtrlExecThread = 0; 1452 1690 if (s_uCtrlExecThread++ == UINT32_MAX) 1691 s_uCtrlExecThread = 0; /* Wrap around to not let IPRT freak out. */ 1453 1692 rc = RTThreadCreateF(&pThread->Thread, VBoxServiceControlThread, 1454 1693 pThread /*pvUser*/, 0 /*cbStack*/, 1455 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "controlexec%u", s_uCtrlExecThread++);1694 RTTHREADTYPE_DEFAULT, 0 /* Flags */, "gctl%u", s_uCtrlExecThread); 1456 1695 if (RT_FAILURE(rc)) 1457 1696 { … … 1505 1744 if (pThread) 1506 1745 { 1507 /* Set request result to some defined state in case 1508 * it got cancelled. */ 1509 pRequest->rc = VERR_CANCELLED; 1510 1511 /* Set request structure pointer. */ 1512 pThread->pRequest = pRequest; 1513 1514 /** @todo To speed up simultaneous guest process handling we could add a worker threads 1515 * or queue in order to wait for the request to happen. Later. */ 1516 1517 /* Wake up guest thrad by sending a wakeup byte to the notification pipe so 1518 * that RTPoll unblocks (returns) and we then can do our requested operation. */ 1519 if (pThread->hNotificationPipeW == NIL_RTPIPE) 1520 rc = VERR_BROKEN_PIPE; 1521 size_t cbWritten; 1522 if (RT_SUCCESS(rc)) 1523 rc = RTPipeWrite(pThread->hNotificationPipeW, "i", 1, &cbWritten); 1524 1525 if ( RT_SUCCESS(rc) 1526 && cbWritten) 1527 { 1528 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Waiting for response on enmType=%u, pvData=0x%p, cbData=%u\n", 1529 uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData); 1530 /* Wait on the request to get completed (or we are asked to abort/shutdown). */ 1531 rc = RTSemEventMultiWait(pThread->RequestEvent, RT_INDEFINITE_WAIT); 1746 if (ASMAtomicReadBool(&pThread->fShutdown)) 1747 { 1748 rc = VERR_CANCELLED; 1749 } 1750 else 1751 { 1752 /* Set request structure pointer. */ 1753 pThread->pRequest = pRequest; 1754 1755 /** @todo To speed up simultaneous guest process handling we could add a worker threads 1756 * or queue in order to wait for the request to happen. Later. */ 1757 /* Wake up guest thrad by sending a wakeup byte to the notification pipe so 1758 * that RTPoll unblocks (returns) and we then can do our requested operation. */ 1759 Assert(pThread->hNotificationPipeW != NIL_RTPIPE); 1760 size_t cbWritten; 1532 1761 if (RT_SUCCESS(rc)) 1762 rc = RTPipeWrite(pThread->hNotificationPipeW, "i", 1, &cbWritten); 1763 1764 if ( RT_SUCCESS(rc) 1765 && cbWritten) 1533 1766 { 1534 VBoxServiceVerbose(4, "ControlThread: [PID %u]: Performed with rc=%Rrc, cbData=%u\n", 1535 uPID, pRequest->rc, pRequest->cbData); 1536 1537 /* Give back overall request result. */ 1538 rc = pRequest->rc; 1539 1540 /* Reset the semaphore. */ 1541 int rc2 = RTSemEventMultiReset(pThread->RequestEvent); 1542 if (RT_FAILURE(rc2)) 1543 VBoxServiceError("ControlThread: [PID %u]: Unable to reset request event, rc=%Rrc\n", 1544 uPID, rc2); 1767 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Waiting for response on enmType=%u, pvData=0x%p, cbData=%u\n", 1768 uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData); 1769 1770 rc = VBoxServiceControlThreadRequestWait(pRequest); 1545 1771 } 1546 else1547 VBoxServiceError("ControlThread: [PID %u]: Wait failed, rc=%Rrc\n",1548 uPID, rc);1549 1772 } 1550 1773 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r39515 r39843 163 163 typedef struct VBOXSERVICECTRLREQUEST 164 164 { 165 /** Event semaphore to serialize access. */ 166 RTSEMEVENTMULTI Event; 165 167 /** The request type to handle. */ 166 168 VBOXSERVICECTRLREQUESTTYPE enmType; … … 172 174 void *pvData; 173 175 /** The context ID which is required to complete the 174 * request. */176 * request. Not used at the moment. */ 175 177 uint32_t uCID; 176 178 /** The overall result of the operation. */ … … 189 191 /** The worker thread. */ 190 192 RTTHREAD Thread; 191 /** Shutdown indicator. */ 193 /** Shutdown indicator; will be set when the thread 194 * needs (or is asked) to shutdown. */ 192 195 bool volatile fShutdown; 193 196 /** Indicator set by the service thread exiting. */ … … 218 221 * is allowed to run. 0 for indefinite time. */ 219 222 uint32_t uTimeLimitMS; 220 RTSEMEVENTMULTI RequestEvent;221 223 /** Pointer to the current IPC request being 222 224 * processed. */ … … 233 235 /** Pointer to thread data. */ 234 236 typedef VBOXSERVICECTRLTHREAD *PVBOXSERVICECTRLTHREAD; 235 236 /**237 * Request types to perform on a started guest process.238 */239 typedef enum VBOXSERVICECTRLTHREADSTATUS240 {241 /** Unknown status. Do not use / should not happen. */242 VBOXSERVICECTRLTHREADSTATUS_UNKNOWN = 0,243 VBOXSERVICECTRLTHREADSTATUS_STARTED = 100,244 VBOXSERVICECTRLTHREADSTATUS_STOPPED = 200245 } VBOXSERVICECTRLTHREADSTATUS;246 237 #endif /* VBOX_WITH_GUEST_CONTROL */ 247 238 #ifdef VBOX_WITH_GUEST_PROPS … … 345 336 extern void VBoxServiceControlRemoveThread(const PVBOXSERVICECTRLTHREAD pThread); 346 337 /* Guest process functions. */ 347 extern VBOXSERVICECTRLTHREADSTATUS VBoxServiceControlThreadGetStatus(const PVBOXSERVICECTRLTHREAD pThread);338 extern bool VBoxServiceControlThreadActive(const PVBOXSERVICECTRLTHREAD pThread); 348 339 extern int VBoxServiceControlThreadStart(uint32_t uClientID, uint32_t uContext, 349 340 const char *pszCmd, uint32_t uFlags, … … 352 343 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS, 353 344 PRTLISTNODE *ppNode); 345 extern int VBoxServiceControlThreadRequestAlloc(PVBOXSERVICECTRLREQUEST *ppReq, 346 VBOXSERVICECTRLREQUESTTYPE enmType); 347 extern int VBoxServiceControlThreadRequestAllocEx(PVBOXSERVICECTRLREQUEST *ppReq, 348 VBOXSERVICECTRLREQUESTTYPE enmType, 349 void* pbData, 350 size_t cbData, 351 uint32_t uCID); 352 extern void VBoxServiceControlThreadRequestFree(PVBOXSERVICECTRLREQUEST pReq); 354 353 extern int VBoxServiceControlThreadPerform(uint32_t uPID, PVBOXSERVICECTRLREQUEST pRequest); 355 354 extern int VBoxServiceControlThreadSignalShutdown(const PVBOXSERVICECTRLTHREAD pThread);
Note:
See TracChangeset
for help on using the changeset viewer.