Changeset 39418 in vbox for trunk/src/VBox/Additions/common/VBoxService
- Timestamp:
- Nov 25, 2011 10:11:06 AM (13 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
r39392 r39418 314 314 /* Tell the host. */ 315 315 rc = VbglR3GuestCtrlExecReportStatus(uClientID, uContextID, 0 /* PID, invalid. */, 316 PROC_STS_ERROR, VERR_MAX_PROCS_REACHED, 316 PROC_STS_ERROR, 317 !fAllowed ? VERR_MAX_PROCS_REACHED : rc, 317 318 NULL /* pvData */, 0 /* cbData */); 318 319 } … … 335 336 * @param pcbRead Pointer to number of bytes read. Optional. 336 337 */ 337 int VBoxServiceControlExecGetOutput(uint32_t uPID, uint32_t uHandleId, uint32_t uTimeout, 338 int VBoxServiceControlExecGetOutput(uint32_t uPID, uint32_t uCID, 339 uint32_t uHandleId, uint32_t uTimeout, 338 340 void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead) 339 341 { … … 345 347 346 348 VBOXSERVICECTRLREQUEST ctrlRequest; 349 ctrlRequest.uCID = uCID; 347 350 ctrlRequest.cbData = cbBuf; 348 351 ctrlRequest.pvData = (uint8_t*)pvBuf; … … 389 392 * @param pcbWritten Pointer to number of bytes written to the process. Optional. 390 393 */ 391 int VBoxServiceControlSetInput(uint32_t uPID, bool fPendingClose, 394 int VBoxServiceControlSetInput(uint32_t uPID, uint32_t uCID, 395 bool fPendingClose, 392 396 void *pvBuf, uint32_t cbBuf, 393 397 uint32_t *pcbWritten) … … 400 404 401 405 VBOXSERVICECTRLREQUEST ctrlRequest; 406 ctrlRequest.uCID = uCID; 402 407 ctrlRequest.cbData = cbBuf; 403 408 ctrlRequest.pvData = pvBuf; … … 470 475 } 471 476 472 rc = VBoxServiceControlSetInput(uPID, fPendingClose, pabBuffer,477 rc = VBoxServiceControlSetInput(uPID, uContextID, fPendingClose, pabBuffer, 473 478 cbSize, &cbWritten); 474 VBoxServiceVerbose(4, "Control: [PID %u]: Written input, rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n",475 uPID, rc, uFlags, fPendingClose, cbSize, cbWritten);479 VBoxServiceVerbose(4, "Control: [PID %u]: Written input, CID=%u, rc=%Rrc, uFlags=0x%x, fPendingClose=%d, cbSize=%u, cbWritten=%u\n", 480 uPID, uContextID, rc, uFlags, fPendingClose, cbSize, cbWritten); 476 481 if (RT_SUCCESS(rc)) 477 482 { … … 543 548 if (pBuf) 544 549 { 545 rc = VBoxServiceControlExecGetOutput(uPID, u HandleID, RT_INDEFINITE_WAIT /* Timeout */,550 rc = VBoxServiceControlExecGetOutput(uPID, uContextID, uHandleID, RT_INDEFINITE_WAIT /* Timeout */, 546 551 pBuf, _64K /* cbSize */, &cbRead); 552 553 /** Note: Don't convert/touch/modify/whatever the output data here! This might be binary 554 * data which the host needs to work with -- so just pass through all data unfiltered! */ 555 547 556 if (RT_SUCCESS(rc)) 548 VBoxServiceVerbose( 3, "Control: [PID %u]: Got output, CID=%u, cbRead=%u, uHandle=%u, uFlags=%u\n",557 VBoxServiceVerbose(2, "Control: Got output, PID=%u, CID=%u, cbRead=%u, uHandle=%u, uFlags=%u\n", 549 558 uPID, uContextID, cbRead, uHandleID, uFlags); 559 else if (rc == VERR_NOT_FOUND) 560 VBoxServiceVerbose(2, "Control: PID=%u not found, CID=%u, uHandle=%u\n", 561 uPID, uContextID, uHandleID, rc); 550 562 else 551 VBoxServiceError("Control: [PID %u]: Failed to retrieve output, CID=%u, uHandle=%u, rc=%Rrc\n",563 VBoxServiceError("Control: Failed to retrieve output for PID=%u, CID=%u, uHandle=%u, rc=%Rrc\n", 552 564 uPID, uContextID, uHandleID, rc); 553 565 /* Note: Since the context ID is unique the request *has* to be completed here, … … 598 610 599 611 612 /** 613 * Destroys all guest process threads which are still active. 614 */ 600 615 static void VBoxServiceControlDestroyThreads(void) 601 616 { 602 VBoxServiceVerbose( 3, "Control: Destroying threads ...\n");617 VBoxServiceVerbose(2, "Control: Destroying threads ...\n"); 603 618 604 619 /* Signal all threads that we want to shutdown. */ … … 625 640 } 626 641 642 #ifdef DEBUG 643 PVBOXSERVICECTRLTHREAD pThreadCur; 644 uint32_t cThreads = 0; 645 RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node) 646 cThreads++; 647 VBoxServiceVerbose(4, "Control: Guest process threads left=%u\n", cThreads); 648 #endif 627 649 AssertMsg(RTListIsEmpty(&g_GuestControlThreads), 628 650 ("Guest process thread list still contains children when it should not\n")); … … 680 702 RTListForEach(&g_GuestControlThreads, pThread, VBOXSERVICECTRLTHREAD, Node) 681 703 { 682 // THREAD LOCKING!! 683 Assert(pThread->fStarted != pThread->fStopped); 684 if (pThread->fStarted) 704 VBOXSERVICECTRLTHREADSTATUS enmStatus = VBoxServiceControlThreadGetStatus(pThread); 705 if (enmStatus == VBOXSERVICECTRLTHREADSTATUS_STARTED) 685 706 uProcsRunning++; 686 else if ( pThread->fStopped)707 else if (enmStatus == VBOXSERVICECTRLTHREADSTATUS_STOPPED) 687 708 uProcsStopped++; 688 709 else … … 690 711 } 691 712 692 VBoxServiceVerbose( 2, "Control: Maximum served guest processes set to %u, running=%u, stopped=%u\n",713 VBoxServiceVerbose(3, "Control: Maximum served guest processes set to %u, running=%u, stopped=%u\n", 693 714 g_GuestControlProcsMaxKept, uProcsRunning, uProcsStopped); 694 715 … … 714 735 715 736 /** 716 * Finds a (formerly) started process given by its PID. 737 * Finds a (formerly) started process given by its PID and locks it. Must be unlocked 738 * by the caller with VBoxServiceControlThreadUnlock(). 717 739 * 718 740 * @return PVBOXSERVICECTRLTHREAD Process structure if found, otherwise NULL. 719 741 * @param uPID PID to search for. 720 742 */ 721 PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadByPID(uint32_t uPID)743 const PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadLocked(uint32_t uPID) 722 744 { 723 745 PVBOXSERVICECTRLTHREAD pThread = NULL; … … 730 752 if (pThreadCur->uPID == uPID) 731 753 { 732 pThread = pThreadCur; 754 rc = RTCritSectEnter(&pThreadCur->CritSect); 755 if (RT_SUCCESS(rc)) 756 pThread = pThreadCur; 733 757 break; 734 758 } … … 745 769 746 770 /** 771 * Unlocks a previously locked guest process thread. 772 * 773 * @param pThread Thread to unlock. 774 */ 775 void VBoxServiceControlThreadUnlock(const PVBOXSERVICECTRLTHREAD pThread) 776 { 777 AssertPtr(pThread); 778 779 int rc = RTCritSectLeave(&pThread->CritSect); 780 AssertRC(rc); 781 } 782 783 784 /** 785 * Assigns a valid PID to a guest control thread and also checks if there already was 786 * another (stale) guest process which was using that PID before and destroys it. 787 * 788 * @return IPRT status code. 789 * @param pThread Thread to assign PID to. 790 * @param uPID PID to assign to the specified guest control execution thread. 791 */ 792 int VBoxServiceControlAssignPID(PVBOXSERVICECTRLTHREAD pThread, uint32_t uPID) 793 { 794 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 795 AssertReturn(uPID, VERR_INVALID_PARAMETER); 796 797 int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect); 798 if (RT_SUCCESS(rc)) 799 { 800 /* Search old threads using the desired PID and shut them down completely -- it's 801 * not used anymore. */ 802 PVBOXSERVICECTRLTHREAD pThreadCur; 803 RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node) 804 { 805 if ( pThreadCur->uPID == uPID 806 && pThreadCur != pThread) 807 { 808 VBoxServiceVerbose(2, "ControlThread: PID %u was used before, shutting down stale exec thread ...\n", 809 uPID); 810 rc = VBoxServiceControlThreadSignalShutdown(pThreadCur); 811 if (RT_SUCCESS(rc)) 812 rc = VBoxServiceControlThreadWaitForShutdown(pThreadCur, 813 30 * 1000 /* Wait 30 seconds max. */); 814 } 815 } 816 817 /* Assign PID to current thread. */ 818 pThread->uPID = uPID; 819 820 rc = RTCritSectLeave(&g_GuestControlThreadsCritSect); 821 AssertRC(rc); 822 } 823 824 return rc; 825 } 826 827 828 /** 747 829 * Removes the specified guest process thread from the global thread 748 830 * list. … … 751 833 * @param pThread Thread to remove. 752 834 */ 753 void VBoxServiceControlRemoveThread( PVBOXSERVICECTRLTHREAD pThread)835 void VBoxServiceControlRemoveThread(const PVBOXSERVICECTRLTHREAD pThread) 754 836 { 755 837 if (!pThread) … … 763 845 RTListNodeRemove(&pThread->Node); 764 846 765 int rc2 = RTCritSectLeave(&g_GuestControlThreadsCritSect); 766 AssertRC(rc2); 847 #ifdef DEBUG 848 PVBOXSERVICECTRLTHREAD pThreadCur; 849 uint32_t cThreads = 0; 850 RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node) 851 cThreads++; 852 VBoxServiceVerbose(4, "Control: Guest process threads left=%u\n", cThreads); 853 #endif 854 rc = RTCritSectLeave(&g_GuestControlThreadsCritSect); 855 AssertRC(rc); 767 856 } 768 857 } -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp
r39393 r39418 42 42 43 43 /* Internal functions. */ 44 static int vboxServiceControlThreadAssignPID(PVBOXSERVICECTRLTHREAD pData, uint32_t uPID); 45 static void vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pData); 46 static int vboxServiceControlThreadShutdown(PVBOXSERVICECTRLTHREAD pThread); 44 static int vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread); 47 45 48 46 /** … … 154 152 155 153 /** 154 * Frees a guest thread. 155 * 156 * @return IPRT status code. 157 * @param pThread Thread to shut down. 158 */ 159 static int vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread) 160 { 161 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 162 163 VBoxServiceVerbose(1, "ControlThread: [PID %u]: Shutting down ...\n", 164 pThread->uPID); 165 166 /* Signal the request event to unblock potential waiters. */ 167 int rc = RTSemEventMultiSignal(pThread->RequestEvent); 168 if (RT_FAILURE(rc)) 169 VBoxServiceError("ControlThread: [PID %u]: Signalling request event failed, rc=%Rrc\n", 170 pThread->uPID, rc); 171 172 rc = RTCritSectEnter(&pThread->CritSect); 173 if (RT_SUCCESS(rc)) 174 { 175 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Freeing thread data ...\n", 176 pThread->uPID); 177 178 RTStrFree(pThread->pszCmd); 179 if (pThread->uNumEnvVars) 180 { 181 for (uint32_t i = 0; i < pThread->uNumEnvVars; i++) 182 RTStrFree(pThread->papszEnv[i]); 183 RTMemFree(pThread->papszEnv); 184 } 185 RTGetOptArgvFree(pThread->papszArgs); 186 RTStrFree(pThread->pszUser); 187 RTStrFree(pThread->pszPassword); 188 189 rc = RTSemEventMultiDestroy(pThread->RequestEvent); 190 AssertRC(rc); 191 192 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Cleaning up ...\n", 193 pThread->uPID); 194 195 /* Set stopped status. */ 196 ASMAtomicXchgBool(&pThread->fStopped, true); 197 198 rc = RTCritSectLeave(&pThread->CritSect); 199 AssertRC(rc); 200 } 201 202 /* 203 * Destroy other thread data. 204 */ 205 if (RTCritSectIsInitialized(&pThread->CritSect)) 206 RTCritSectDelete(&pThread->CritSect); 207 208 /* 209 * Destroy thread structure as final step. 210 */ 211 RTMemFree(pThread); 212 pThread = NULL; 213 214 return rc; 215 } 216 217 218 /** 156 219 * Signals a guest process thread that we want it to shut down in 157 220 * a gentle way. … … 164 227 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 165 228 166 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Signalling shutdown ...\n",229 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Signalling shutdown ...\n", 167 230 pThread->uPID); 168 231 … … 176 239 int rc = VBoxServiceControlThreadPerform(pThread->uPID, &ctrlRequest); 177 240 if (RT_FAILURE(rc)) 178 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Sending quit request failed with rc=%Rrc\n",241 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Sending quit request failed with rc=%Rrc\n", 179 242 pThread->uPID, rc); 180 243 return rc; … … 197 260 && !ASMAtomicReadBool(&pThread->fStopped)) /* Only shutdown threads which aren't yet. */ 198 261 { 199 VBoxServiceVerbose( 3, "ControlThead: [PID %u]: Waiting for shutdown ...\n",262 VBoxServiceVerbose(2, "ControlThread: [PID %u]: Waiting for shutdown ...\n", 200 263 pThread->uPID); 201 264 … … 205 268 if (RT_FAILURE(rcThread)) 206 269 { 207 VBoxServiceError("ControlTh ead: [PID %u]: Shutdown returned error rc=%Rrc\n",270 VBoxServiceError("ControlThread: [PID %u]: Shutdown returned error rc=%Rrc\n", 208 271 pThread->uPID, rcThread); 209 272 if (RT_SUCCESS(rc)) … … 216 279 217 280 /** 218 * Frees an allocated thread data structure along with all its allocated parameters. 219 * 220 * @param pThread Pointer to thread data to free. 221 */ 222 static void vboxServiceControlThreadFree(const PVBOXSERVICECTRLTHREAD pThread) 223 { 224 if (!pThread) 225 return; 226 227 VBoxServiceVerbose(3, "ControlThead: [PID %u]: Freeing thread data ...\n", 228 pThread->uPID); 229 230 RTStrFree(pThread->pszCmd); 231 if (pThread->uNumEnvVars) 232 { 233 for (uint32_t i = 0; i < pThread->uNumEnvVars; i++) 234 RTStrFree(pThread->papszEnv[i]); 235 RTMemFree(pThread->papszEnv); 236 } 237 RTGetOptArgvFree(pThread->papszArgs); 238 RTStrFree(pThread->pszUser); 239 RTStrFree(pThread->pszPassword); 240 241 if (pThread->RequestEvent != NIL_RTSEMEVENTMULTI) 242 { 243 int rc2 = RTSemEventMultiDestroy(pThread->RequestEvent); 244 AssertRC(rc2); 245 } 281 * Returns the guest process thread's current status. 282 * 283 * @return VBOXSERVICECTRLTHREADSTATUS 284 * @param pThread Thread to determine current status for. 285 */ 286 VBOXSERVICECTRLTHREADSTATUS VBoxServiceControlThreadGetStatus(const PVBOXSERVICECTRLTHREAD pThread) 287 { 288 AssertPtrReturn(pThread, VBOXSERVICECTRLTHREADSTATUS_UNKNOWN); 289 290 int rc = RTCritSectEnter(&pThread->CritSect); 291 if (RT_SUCCESS(rc)) 292 { 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")); 304 305 rc = RTCritSectLeave(&pThread->CritSect); 306 AssertRC(rc); 307 308 return enmStatus; 309 } 310 311 return VBOXSERVICECTRLTHREADSTATUS_UNKNOWN; 246 312 } 247 313 … … 294 360 * 295 361 */ 362 static int VBoxServiceControlThreadHandleOutputError(RTPOLLSET hPollSet, uint32_t fPollEvt, 363 PRTPIPE phPipeR, uint32_t idPollHnd) 364 { 365 int rc = VINF_SUCCESS; 366 367 rc = RTPollSetRemove(hPollSet, idPollHnd); 368 AssertRC(rc); 369 370 rc = RTPipeClose(*phPipeR); 371 AssertRC(rc); 372 *phPipeR = NIL_RTPIPE; 373 374 return rc; 375 } 376 377 378 /** 379 * Handle pending output data or error on standard out or standard error. 380 * 381 * @returns IPRT status code from client send. 382 * @param hPollSet The polling set. 383 * @param fPollEvt The event mask returned by RTPollNoResume. 384 * @param phPipeR The pipe handle. 385 * @param idPollHnd The pipe ID to handle. 386 * 387 */ 296 388 static int VBoxServiceControlThreadHandleOutputEvent(RTPOLLSET hPollSet, uint32_t fPollEvt, 297 389 PRTPIPE phPipeR, uint32_t idPollHnd) 298 390 { 299 391 int rc = VINF_SUCCESS; 300 301 #if 0 302 if (fPollEvt & RTPOLL_EVT_READ) 303 { 304 /** @todo Later: Notify the host about the read operation! */ 305 306 /* Make sure we go another poll round in case there was too much data 307 for the buffer to hold. */ 308 fPollEvt &= RTPOLL_EVT_ERROR; 309 310 /* Remove read event from poll set and just poll for errors from now on. 311 * This is necessary for doing a RTPipeRead. */ 312 rc = RTPollSetEventsChange(hPollSet, idPollHnd, RTPOLL_EVT_ERROR); 313 AssertRC(rc); 314 } 392 if (fPollEvt == RTPOLL_EVT_READ) 393 { 394 char abBuf[_64K]; 395 size_t cbRead; 396 int rc = RTPipeRead(*phPipeR, abBuf, sizeof(abBuf), &cbRead); 397 if (RT_SUCCESS(rc) && cbRead) 398 { 399 #ifdef DEBUG 400 VBoxServiceVerbose(4, "ControlThread: Drain idPollHnd=%u, abBuf=0x%p, cbRead=%u\n", 401 idPollHnd, abBuf, cbRead); 315 402 #endif 316 403 /* Goes to bit bucket ... */ 404 405 /* Make sure we go another poll round in case there was too much data 406 for the buffer to hold. */ 407 fPollEvt &= RTPOLL_EVT_ERROR; 408 } 409 else if (RT_FAILURE(rc)) 410 { 411 fPollEvt |= RTPOLL_EVT_ERROR; 412 AssertMsg(rc == VERR_BROKEN_PIPE, ("%Rrc\n", rc)); 413 } 414 } 415 416 if (fPollEvt & RTPOLL_EVT_ERROR) 417 rc = VBoxServiceControlThreadHandleOutputError(hPollSet, fPollEvt, 418 phPipeR, idPollHnd); 419 return rc; 420 } 421 422 423 static int VBoxServiceControlThreadHandleRequest(RTPOLLSET hPollSet, uint32_t fPollEvt, 424 PRTPIPE phStdInW, PRTPIPE phStdOutR, PRTPIPE phStdErrR, 425 PVBOXSERVICECTRLTHREAD pThread) 426 { 317 427 #ifdef DEBUG_andy 318 VBoxServiceVerbose(4, "ControlThead: HandleOutputEvent fPollEvt=0x%x, idPollHnd=%u\n", 319 fPollEvt, idPollHnd); 320 #endif 321 322 /* 323 * If an error was raised signalled 324 */ 325 if (fPollEvt & RTPOLL_EVT_ERROR) 326 { 327 rc = RTPollSetRemove(hPollSet, idPollHnd); 328 AssertRC(rc); 329 330 rc = RTPipeClose(*phPipeR); 331 AssertRC(rc); 332 *phPipeR = NIL_RTPIPE; 333 } 334 335 return rc; 336 } 337 338 339 static int VBoxServiceControlThreadHandleIPCRequest(RTPOLLSET hPollSet, uint32_t fPollEvt, 340 PRTPIPE phStdInW, PRTPIPE phStdOutR, PRTPIPE phStdErrR, 341 PVBOXSERVICECTRLTHREAD pThread) 342 { 343 #ifdef DEBUG_andy 344 VBoxServiceVerbose(4, "ControlThead: HandleIPCRequest\n"); 428 VBoxServiceVerbose(4, "ControlThread: HandleIPCRequest\n"); 345 429 #endif 346 430 … … 350 434 AssertPtrReturn(phStdErrR, VERR_INVALID_POINTER); 351 435 352 int rc = RTCritSectEnter(&pThread->CritSect);436 /*int rc = RTCritSectEnter(&pThread->CritSect); 353 437 if (RT_SUCCESS(rc)) 354 { 438 {*/ 355 439 /* Drain the notification pipe. */ 356 440 uint8_t abBuf[8]; … … 358 442 rc = RTPipeRead(pThread->hNotificationPipeR, abBuf, sizeof(abBuf), &cbIgnore); 359 443 if (RT_FAILURE(rc)) 360 VBoxServiceError("ControlTh ead: Draining IPC notification pipe failed with rc=%Rrc\n", rc);444 VBoxServiceError("ControlThread: Draining IPC notification pipe failed with rc=%Rrc\n", rc); 361 445 362 446 int rcReq = VINF_SUCCESS; /* Actual request result. */ … … 438 522 ? rcReq : rc; 439 523 440 VBoxServiceVerbose( 4, "ControlThead: Handled IPC request with rcReq=%Rrc, enmType=%u, cbData=%u\n",441 rcReq, pRequest->enmType, pRequest->cbData);524 VBoxServiceVerbose(2, "ControlThread: [PID %u]: Handled req=%u, CID=%u, rcReq=%Rrc, cbData=%u\n", 525 pThread->uPID, pRequest->enmType, pRequest->uCID, rcReq, pRequest->cbData); 442 526 443 527 /* In any case, regardless of the result, we notify … … 448 532 * or modified already! */ 449 533 450 rc2 = RTCritSectLeave(&pThread->CritSect);534 /*rc2 = RTCritSectLeave(&pThread->CritSect); 451 535 AssertRC(rc2); 452 } 536 }*/ 453 537 454 538 return rc; … … 475 559 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 476 560 AssertPtrReturn(phStdInW, VERR_INVALID_PARAMETER); 477 AssertPtrReturn(phStdOutR, VERR_INVALID_PARAMETER); 478 AssertPtrReturn(phStdErrR, VERR_INVALID_PARAMETER); 561 /* Rest is optional. */ 479 562 480 563 int rc; … … 495 578 * the first (stale) entry will be found and we get really weird results! 496 579 */ 497 rc = vboxServiceControlThreadAssignPID(pThread, hProcess);580 rc = VBoxServiceControlAssignPID(pThread, hProcess); 498 581 if (RT_FAILURE(rc)) 499 582 { 500 VBoxServiceError("ControlThead: Unable to assign PID to new thread, rc=%Rrc\n", rc); 583 VBoxServiceError("ControlThread: Unable to assign PID=%u, to new thread, rc=%Rrc\n", 584 hProcess, rc); 501 585 return rc; 502 586 } … … 506 590 * and that it's now OK to send input to the process. 507 591 */ 508 VBoxServiceVerbose( 3, "ControlThead: [PID %u]: Processstarted, CID=%u, User=%s\n",509 pThread->uPID, pThread-> uContextID, pThread->pszUser);592 VBoxServiceVerbose(2, "ControlThread: [PID %u]: Process \"%s\" started, CID=%u, User=%s\n", 593 pThread->uPID, pThread->pszCmd, pThread->uContextID, pThread->pszUser); 510 594 rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID, 511 595 pThread->uPID, PROC_STS_STARTED, 0 /* u32Flags */, … … 531 615 if (RT_SUCCESS(rc2)) 532 616 { 533 /*VBoxServiceVerbose(4, "ControlTh ead: [PID %u}: RTPollNoResume idPollHnd=%u\n",617 /*VBoxServiceVerbose(4, "ControlThread: [PID %u}: RTPollNoResume idPollHnd=%u\n", 534 618 pThread->uPID, idPollHnd);*/ 535 619 switch (idPollHnd) … … 550 634 551 635 case VBOXSERVICECTRLPIPEID_IPC_NOTIFY: 552 rc = VBoxServiceControlThreadHandle IPCRequest(hPollSet, fPollEvt,553 phStdInW,phStdOutR,phStdErrR, pThread);636 rc = VBoxServiceControlThreadHandleRequest(hPollSet, fPollEvt, 637 phStdInW, phStdOutR, phStdErrR, pThread); 554 638 break; 555 639 } … … 608 692 if (cMsElapsed >= cMsTimeout) 609 693 { 610 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Timed out (%ums elapsed > %ums timeout), killing ...",694 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Timed out (%ums elapsed > %ums timeout), killing ...", 611 695 pThread->uPID, cMsElapsed, cMsTimeout); 612 696 … … 644 728 if (MsProcessKilled == UINT64_MAX) 645 729 { 646 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Is still alive and not killed yet\n",730 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Is still alive and not killed yet\n", 647 731 pThread->uPID); 648 732 … … 654 738 for (size_t i = 0; i < 10; i++) 655 739 { 656 VBoxServiceVerbose(4, "ControlTh ead: [PID %u]: Kill attempt %d/10: Waiting to exit ...\n",740 VBoxServiceVerbose(4, "ControlThread: [PID %u]: Kill attempt %d/10: Waiting to exit ...\n", 657 741 pThread->uPID, i + 1); 658 742 rc2 = RTProcWait(hProcess, RTPROCWAIT_FLAGS_NOBLOCK, &ProcessStatus); 659 743 if (RT_SUCCESS(rc2)) 660 744 { 661 VBoxServiceVerbose(4, "ControlTh ead: [PID %u]: Kill attempt %d/10: Exited\n",745 VBoxServiceVerbose(4, "ControlThread: [PID %u]: Kill attempt %d/10: Exited\n", 662 746 pThread->uPID, i + 1); 663 747 fProcessAlive = false; … … 666 750 if (i >= 5) 667 751 { 668 VBoxServiceVerbose(4, "ControlTh ead: [PID %u]: Kill attempt %d/10: Trying to terminate ...\n",752 VBoxServiceVerbose(4, "ControlThread: [PID %u]: Kill attempt %d/10: Trying to terminate ...\n", 669 753 pThread->uPID, i + 1); 670 754 RTProcTerminate(hProcess); … … 674 758 675 759 if (fProcessAlive) 676 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Could not be killed\n", pThread->uPID);760 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Could not be killed\n", pThread->uPID); 677 761 } 678 762 … … 688 772 if ( fProcessTimedOut && !fProcessAlive && MsProcessKilled != UINT64_MAX) 689 773 { 690 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Timed out and got killed\n",774 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Timed out and got killed\n", 691 775 pThread->uPID); 692 776 uStatus = PROC_STS_TOK; … … 694 778 else if (fProcessTimedOut && fProcessAlive && MsProcessKilled != UINT64_MAX) 695 779 { 696 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Timed out and did *not* get killed\n",780 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Timed out and did *not* get killed\n", 697 781 pThread->uPID); 698 782 uStatus = PROC_STS_TOA; … … 700 784 else if (pThread->fShutdown && (fProcessAlive || MsProcessKilled != UINT64_MAX)) 701 785 { 702 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Got terminated because system/service is about to shutdown\n",786 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Got terminated because system/service is about to shutdown\n", 703 787 pThread->uPID); 704 788 uStatus = PROC_STS_DWN; /* Service is stopping, process was killed. */ … … 707 791 else if (fProcessAlive) 708 792 { 709 VBoxServiceError("ControlTh ead: [PID %u]: Is alive when it should not!\n",793 VBoxServiceError("ControlThread: [PID %u]: Is alive when it should not!\n", 710 794 pThread->uPID); 711 795 } 712 796 else if (MsProcessKilled != UINT64_MAX) 713 797 { 714 VBoxServiceError("ControlTh ead: [PID %u]: Has been killed when it should not!\n",798 VBoxServiceError("ControlThread: [PID %u]: Has been killed when it should not!\n", 715 799 pThread->uPID); 716 800 } 717 801 else if (ProcessStatus.enmReason == RTPROCEXITREASON_NORMAL) 718 802 { 719 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Ended with RTPROCEXITREASON_NORMAL (%u)\n",803 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_NORMAL (%u)\n", 720 804 pThread->uPID, ProcessStatus.iStatus); 721 805 … … 725 809 else if (ProcessStatus.enmReason == RTPROCEXITREASON_SIGNAL) 726 810 { 727 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Ended with RTPROCEXITREASON_SIGNAL (%u)\n",811 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_SIGNAL (%u)\n", 728 812 pThread->uPID, ProcessStatus.iStatus); 729 813 … … 733 817 else if (ProcessStatus.enmReason == RTPROCEXITREASON_ABEND) 734 818 { 735 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Ended with RTPROCEXITREASON_ABEND (%u)\n",819 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Ended with RTPROCEXITREASON_ABEND (%u)\n", 736 820 pThread->uPID, ProcessStatus.iStatus); 737 821 … … 740 824 } 741 825 else 742 VBoxServiceVerbose(1, "ControlTh ead: [PID %u]: Handling process status %u not implemented\n",826 VBoxServiceVerbose(1, "ControlThread: [PID %u]: Handling process status %u not implemented\n", 743 827 pThread->uPID, ProcessStatus.enmReason); 744 828 745 VBoxServiceVerbose( 3, "ControlThead: [PID %u]: Sending final status, ClientID=%u, CID=%u, Status=%u, Flags=0x%x\n",829 VBoxServiceVerbose(2, "ControlThread: [PID %u]: Ended, ClientID=%u, CID=%u, Status=%u, Flags=0x%x\n", 746 830 pThread->uPID, pThread->uClientID, pThread->uContextID, uStatus, uFlags); 747 831 rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID, … … 749 833 NULL /* pvData */, 0 /* cbData */); 750 834 if (RT_FAILURE(rc)) 751 VBoxServiceError("ControlTh ead: [PID %u]: Error reporting final status to host; rc=%Rrc\n",835 VBoxServiceError("ControlThread: [PID %u]: Error reporting final status to host; rc=%Rrc\n", 752 836 pThread->uPID, rc); 753 837 754 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Process loop ended with rc=%Rrc\n",838 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Process loop ended with rc=%Rrc\n", 755 839 pThread->uPID, rc); 756 840 } 757 841 else 758 VBoxServiceError("ControlTh ead: [PID %u]: Loop failed with rc=%Rrc\n",842 VBoxServiceError("ControlThread: [PID %u]: Loop failed with rc=%Rrc\n", 759 843 pThread->uPID, rc); 760 844 return rc; 845 } 846 847 848 static int vboxServiceControlThreadInitPipe(PRTHANDLE ph, PRTPIPE phPipe) 849 { 850 AssertPtrReturn(ph, VERR_INVALID_PARAMETER); 851 AssertPtrReturn(phPipe, VERR_INVALID_PARAMETER); 852 853 ph->enmType = RTHANDLETYPE_PIPE; 854 ph->u.hPipe = NIL_RTPIPE; 855 *phPipe = NIL_RTPIPE; 856 857 return VINF_SUCCESS; 761 858 } 762 859 … … 781 878 AssertPtrReturn(phPipe, VERR_INVALID_PARAMETER); 782 879 783 ph->enmType = RTHANDLETYPE_PIPE;784 ph->u.hPipe = NIL_RTPIPE;785 *pph = NULL;786 *phPipe = NIL_RTPIPE;787 788 880 int rc; 789 881 … … 833 925 #endif 834 926 #ifdef DEBUG 835 VBoxServiceVerbose(3, "ControlTh ead: VBoxServiceControlExecMakeFullPath: %s -> %s\n",927 VBoxServiceVerbose(3, "ControlThread: VBoxServiceControlExecMakeFullPath: %s -> %s\n", 836 928 pszPath, pszExpanded); 837 929 #endif … … 870 962 rc = VBoxServiceControlThreadMakeFullPath(pszExecResolved, pszResolved, cbResolved); 871 963 #ifdef DEBUG 872 VBoxServiceVerbose(3, "ControlTh ead: VBoxServiceControlExecResolveExecutable: %s -> %s\n",964 VBoxServiceVerbose(3, "ControlThread: VBoxServiceControlExecResolveExecutable: %s -> %s\n", 873 965 pszFileName, pszResolved); 874 966 #endif … … 1024 1116 if (fFlags) 1025 1117 { 1026 /* Process Main flag "ExecuteProcessFlag_Hidden". */ 1027 if (fFlags & RT_BIT(2)) 1118 if (fFlags & EXECUTEPROCESSFLAG_HIDDEN) 1028 1119 uProcFlags |= RTPROC_FLAGS_HIDDEN; 1029 /* Process Main flag "ExecuteProcessFlag_NoProfile". */ 1030 if (fFlags & RT_BIT(3)) 1120 if (fFlags & EXECUTEPROCESSFLAG_NO_PROFILE) 1031 1121 uProcFlags |= RTPROC_FLAGS_NO_PROFILE; 1032 1122 } … … 1041 1131 uProcFlags |= RTPROC_FLAGS_SERVICE; 1042 1132 #ifdef DEBUG 1043 VBoxServiceVerbose(3, "ControlTh ead: Command: %s\n", szExecExp);1133 VBoxServiceVerbose(3, "ControlThread: Command: %s\n", szExecExp); 1044 1134 for (size_t i = 0; papszArgsExp[i]; i++) 1045 VBoxServiceVerbose(3, "ControlTh ead:\targv[%ld]: %s\n", i, papszArgsExp[i]);1135 VBoxServiceVerbose(3, "ControlThread:\targv[%ld]: %s\n", i, papszArgsExp[i]); 1046 1136 #endif 1047 1137 /* Do normal execution. */ … … 1066 1156 { 1067 1157 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 1068 VBoxServiceVerbose(3, "ControlTh ead: Thread of process \"%s\" started\n", pThread->pszCmd);1158 VBoxServiceVerbose(3, "ControlThread: Thread of process \"%s\" started\n", pThread->pszCmd); 1069 1159 1070 1160 int rc = VbglR3GuestCtrlConnect(&pThread->uClientID); 1071 1161 if (RT_FAILURE(rc)) 1072 1162 { 1073 VBoxServiceError("ControlTh ead: Thread failed to connect to the guest control service, aborted! Error: %Rrc\n", rc);1163 VBoxServiceError("ControlThread: Thread failed to connect to the guest control service, aborted! Error: %Rrc\n", rc); 1074 1164 RTThreadUserSignal(RTThreadSelf()); 1075 1165 return rc; 1076 1166 } 1077 VBoxServiceVerbose(3, "ControlTh ead: Guest process \"%s\" got client ID=%u\n",1078 pThread->pszCmd, pThread->uClientID );1167 VBoxServiceVerbose(3, "ControlThread: Guest process \"%s\" got client ID=%u, flags=0x%x\n", 1168 pThread->pszCmd, pThread->uClientID, pThread->uFlags); 1079 1169 1080 1170 bool fSignalled = false; /* Indicator whether we signalled the thread user event already. */ … … 1130 1220 /* Stdout. */ 1131 1221 if (RT_SUCCESS(rc)) 1132 rc = RTPollSetAddPipe(hPollSet, hStdOutR, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDOUT); 1222 { 1223 uint32_t uFlags = RTPOLL_EVT_ERROR; 1224 if (!(pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDOUT)) 1225 { 1226 uFlags |= RTPOLL_EVT_READ; 1227 VBoxServiceVerbose(3, "ControlThread: Host is not interested in getting stdout for \"%s\", poll flags=0x%x\n", 1228 pThread->pszCmd, uFlags); 1229 } 1230 rc = RTPollSetAddPipe(hPollSet, hStdOutR, uFlags, VBOXSERVICECTRLPIPEID_STDOUT); 1231 } 1133 1232 /* Stderr. */ 1134 1233 if (RT_SUCCESS(rc)) 1135 rc = RTPollSetAddPipe(hPollSet, hStdErrR, RTPOLL_EVT_ERROR, VBOXSERVICECTRLPIPEID_STDERR); 1234 { 1235 uint32_t uFlags = RTPOLL_EVT_ERROR; 1236 if (!(pThread->uFlags & EXECUTEPROCESSFLAG_WAIT_STDERR)) 1237 { 1238 uFlags |= RTPOLL_EVT_READ; 1239 VBoxServiceVerbose(3, "ControlThread: Host is not interested in getting stderr for \"%s\", poll flags=0x%x\n", 1240 pThread->pszCmd, uFlags); 1241 } 1242 rc = RTPollSetAddPipe(hPollSet, hStdErrR, uFlags, VBOXSERVICECTRLPIPEID_STDERR); 1243 } 1136 1244 /* IPC notification pipe. */ 1137 1245 if (RT_SUCCESS(rc)) … … 1148 1256 &hProcess); 1149 1257 if (RT_FAILURE(rc)) 1150 VBoxServiceError("ControlTh ead: Error starting process, rc=%Rrc\n", rc);1258 VBoxServiceError("ControlThread: Error starting process, rc=%Rrc\n", rc); 1151 1259 /* 1152 1260 * Tell the control thread that it can continue … … 1176 1284 hProcess, pThread->uTimeLimitMS, hPollSet, 1177 1285 &pThread->pipeStdInW, &hStdOutR, &hStdErrR); 1178 1179 /*1180 * Remove thread from global thread list. After this it's safe to shutdown1181 * and deallocate this thread.1182 */1183 VBoxServiceControlRemoveThread(pThread);1184 1185 1286 /* 1186 1287 * The handles that are no longer in the set have … … 1203 1304 else /* Something went wrong; report error! */ 1204 1305 { 1205 VBoxServiceError("ControlTh ead: Could not start process '%s' (CID: %u)! Error: %Rrc\n",1306 VBoxServiceError("ControlThread: Could not start process '%s' (CID: %u)! Error: %Rrc\n", 1206 1307 pThread->pszCmd, pThread->uContextID, rc); 1207 1308 … … 1210 1311 NULL /* pvData */, 0 /* cbData */); 1211 1312 if (RT_FAILURE(rc2)) 1212 VBoxServiceError("ControlTh ead: Could not report process start error! Error: %Rrc (process error %Rrc)\n",1313 VBoxServiceError("ControlThread: Could not report process start error! Error: %Rrc (process error %Rrc)\n", 1213 1314 rc2, rc); 1214 1315 } … … 1238 1339 if (pThread->uClientID) 1239 1340 { 1240 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Cancelling pending waits (client ID=%u)\n",1341 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Cancelling pending waits (client ID=%u)\n", 1241 1342 pThread->uPID, pThread->uClientID); 1242 1343 int rc2 = VbglR3GuestCtrlCancelPendingWaits(pThread->uClientID); 1243 1344 if (RT_FAILURE(rc2)) 1244 1345 { 1245 VBoxServiceError("ControlTh ead: [PID %u]: Cancelling pending waits failed; rc=%Rrc\n",1346 VBoxServiceError("ControlThread: [PID %u]: Cancelling pending waits failed; rc=%Rrc\n", 1246 1347 pThread->uPID, rc2); 1247 1348 if (RT_SUCCESS(rc)) … … 1250 1351 1251 1352 /* Disconnect from guest control service. */ 1252 VBoxService Error("ControlThead: [PID %u]: Disconnecting (client ID=%u) ...\n",1253 pThread->uPID, pThread->uClientID);1353 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Disconnecting (client ID=%u) ...\n", 1354 pThread->uPID, pThread->uClientID); 1254 1355 VbglR3GuestCtrlDisconnect(pThread->uClientID); 1255 1356 pThread->uClientID = 0; 1256 1357 } 1257 1358 1258 VBoxServiceVerbose(3, "ControlTh ead: [PID %u]: Thread of process \"%s\" ended with rc=%Rrc\n",1359 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Thread of process \"%s\" ended with rc=%Rrc\n", 1259 1360 pThread->uPID, pThread->pszCmd, rc); 1260 1361 … … 1268 1369 RTThreadUserSignal(RTThreadSelf()); 1269 1370 1270 int rc2 = vboxServiceControlThreadShutdown(pThread); 1371 /* 1372 * Remove thread from global thread list. After this it's safe to shutdown 1373 * and deallocate this thread. 1374 */ 1375 VBoxServiceControlRemoveThread(pThread); 1376 1377 int rc2 = vboxServiceControlThreadFree(pThread); 1271 1378 if (RT_SUCCESS(rc)) 1272 1379 rc = rc2; … … 1348 1455 if (RT_FAILURE(rc)) 1349 1456 { 1350 VBoxServiceError("ControlTh ead: RTThreadCreate failed, rc=%Rrc\n, pThread=%p\n",1457 VBoxServiceError("ControlThread: RTThreadCreate failed, rc=%Rrc\n, pThread=%p\n", 1351 1458 rc, pThread); 1352 1459 } 1353 1460 else 1354 1461 { 1355 VBoxServiceVerbose(4, "ControlTh ead: Waiting for thread to initialize ...\n");1462 VBoxServiceVerbose(4, "ControlThread: Waiting for thread to initialize ...\n"); 1356 1463 1357 1464 /* Wait for the thread to initialize. */ … … 1359 1466 if (ASMAtomicReadBool(&pThread->fShutdown)) 1360 1467 { 1361 VBoxServiceError("ControlTh ead: Thread for process \"%s\" failed to start!\n", pszCmd);1468 VBoxServiceError("ControlThread: Thread for process \"%s\" failed to start!\n", pszCmd); 1362 1469 rc = VERR_GENERAL_FAILURE; 1363 1470 } … … 1380 1487 1381 1488 /** 1382 * Assigns a valid PID to a guest control thread and also checks if there already was1383 * another (stale) guest process which was using that PID before and destroys it.1384 *1385 * @return IPRT status code.1386 * @param pData Pointer to guest control execution thread data.1387 * @param uPID PID to assign to the specified guest control execution thread.1388 */1389 int vboxServiceControlThreadAssignPID(PVBOXSERVICECTRLTHREAD pThread, uint32_t uPID)1390 {1391 AssertPtrReturn(pThread, VERR_INVALID_POINTER);1392 AssertReturn(uPID, VERR_INVALID_PARAMETER);1393 1394 int rc = VINF_SUCCESS;1395 1396 /* Search an old thread using the desired PID and shut it down completely -- it's1397 * not used anymore. */1398 PVBOXSERVICECTRLTHREAD pOldThread = VBoxServiceControlGetThreadByPID(uPID);1399 if ( pOldThread1400 && pOldThread != pThread)1401 {1402 PVBOXSERVICECTRLTHREAD pNext = RTListNodeGetNext(&pOldThread->Node, VBOXSERVICECTRLTHREAD, Node);1403 1404 VBoxServiceVerbose(3, "ControlThead: PID %u was used before, shutting down stale exec thread ...\n",1405 uPID);1406 rc = vboxServiceControlThreadShutdown(pOldThread);1407 if (RT_FAILURE(rc))1408 {1409 VBoxServiceVerbose(3, "ControlThead: Unable to shut down stale exec thread, rc=%Rrc\n", rc);1410 /* Keep going. */1411 }1412 }1413 1414 /* Assign PID to current thread. */1415 pThread->uPID = uPID;1416 1417 return rc;1418 }1419 1420 1421 /**1422 1489 * Performs a request to a specific (formerly started) guest process and waits 1423 1490 * for its response. … … 1433 1500 /* Rest in pRequest is optional (based on the request type). */ 1434 1501 1435 VBoxServiceVerbose(4, "ControlThead: Performing PID=%u, enmType=%u, pvData=0x%p, cbData=%u ...\n", 1436 uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData); 1437 1438 int rc; 1439 const PVBOXSERVICECTRLTHREAD pThread = VBoxServiceControlGetThreadByPID(uPID); 1440 if ( pThread 1441 && !ASMAtomicReadBool(&pThread->fStopped)) 1442 { 1443 rc = RTCritSectEnter(&pThread->CritSect); 1502 int rc = VINF_SUCCESS; 1503 const PVBOXSERVICECTRLTHREAD pThread = VBoxServiceControlGetThreadLocked(uPID); 1504 if (pThread) 1505 { 1506 /* Set request result to some defined state in case 1507 * it got cancelled. */ 1508 pRequest->rc = VERR_CANCELLED; 1509 1510 /* Set request structure pointer. */ 1511 pThread->pRequest = pRequest; 1512 1513 /** @todo To speed up simultaneous guest process handling we could add a worker threads 1514 * or queue in order to wait for the request to happen. Later. */ 1515 1516 /* Wake up guest thrad by sending a wakeup byte to the notification pipe so 1517 * that RTPoll unblocks (returns) and we then can do our requested operation. */ 1518 if (pThread->hNotificationPipeW == NIL_RTPIPE) 1519 rc = VERR_BROKEN_PIPE; 1520 size_t cbWritten; 1444 1521 if (RT_SUCCESS(rc)) 1445 { 1446 /* Set request structure pointer. */ 1447 pThread->pRequest = pRequest; 1448 1449 /** @todo To speed up simultaneous guest process handling we could add a worker threads 1450 * or queue in order to wait for the request to happen. Later. */ 1451 1452 /* Wake up guest thrad by sending a wakeup byte to the notification pipe so 1453 * that RTPoll unblocks (returns) and we then can do our requested operation. */ 1454 if (pThread->hNotificationPipeW == NIL_RTPIPE) 1455 rc = VERR_BROKEN_PIPE; 1456 size_t cbWritten; 1522 rc = RTPipeWrite(pThread->hNotificationPipeW, "i", 1, &cbWritten); 1523 1524 if ( RT_SUCCESS(rc) 1525 && cbWritten) 1526 { 1527 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Waiting for response on enmType=%u, pvData=0x%p, cbData=%u\n", 1528 uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData); 1529 /* Wait on the request to get completed (or we are asked to abort/shutdown). */ 1530 rc = RTSemEventMultiWait(pThread->RequestEvent, RT_INDEFINITE_WAIT); 1457 1531 if (RT_SUCCESS(rc)) 1458 rc = RTPipeWrite(pThread->hNotificationPipeW, "i", 1, &cbWritten);1459 1460 /* Make sure we leave the critical section before doing the wait. */1461 int rc2 = RTCritSectLeave(&pThread->CritSect);1462 AssertRCReturn(rc2, rc2);1463 1464 if (RT_SUCCESS(rc) && cbWritten)1465 1532 { 1466 VBoxServiceVerbose(4, "ControlThead: [PID %u]: Waiting for response on enmType=%u, pvData=0x%p, cbData=%u\n", 1467 uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData); 1468 /* Wait on the request to get completed (or we are asked to abort/shutdown). */ 1469 rc = RTSemEventMultiWait(pThread->RequestEvent, RT_INDEFINITE_WAIT); 1470 if (RT_SUCCESS(rc)) 1471 { 1472 VBoxServiceVerbose(4, "ControlThead: [PID %u]: Performed with rc=%Rrc, cbData=%u\n", 1473 uPID, pRequest->rc, pRequest->cbData); 1474 1475 rc = RTCritSectEnter(&pThread->CritSect); 1476 if (RT_SUCCESS(rc)) 1477 { 1478 /* Give back overall request result. */ 1479 rc = pRequest->rc; 1480 1481 /* Reset the semaphore. */ 1482 rc2 = RTSemEventMultiReset(pThread->RequestEvent); 1483 if (RT_FAILURE(rc2)) 1484 VBoxServiceError("ControlThead: Unable to reset request event, rc=%Rrc\n", rc2); 1485 1486 rc2 = RTCritSectLeave(&pThread->CritSect); 1487 AssertRCReturn(rc2, rc2); 1488 } 1489 } 1533 VBoxServiceVerbose(4, "ControlThread: [PID %u]: Performed with rc=%Rrc, cbData=%u\n", 1534 uPID, pRequest->rc, pRequest->cbData); 1535 1536 /* Give back overall request result. */ 1537 rc = pRequest->rc; 1538 1539 /* Reset the semaphore. */ 1540 int rc2 = RTSemEventMultiReset(pThread->RequestEvent); 1541 if (RT_FAILURE(rc2)) 1542 VBoxServiceError("ControlThread: [PID %u]: Unable to reset request event, rc=%Rrc\n", 1543 uPID, rc2); 1490 1544 } 1491 } 1545 else 1546 VBoxServiceError("ControlThread: [PID %u]: Wait failed, rc=%Rrc\n", 1547 uPID, rc); 1548 } 1549 1550 VBoxServiceControlThreadUnlock(pThread); 1492 1551 } 1493 1552 else /* PID not found! */ 1494 1553 rc = VERR_NOT_FOUND; 1495 1554 1496 VBoxServiceVerbose(4, "ControlThead: Performed PID=%u, enmType=%u, pvData=0x%p, cbData=%u with rc=%Rrc\n", 1497 uPID, pRequest->enmType, pRequest->pvData, pRequest->cbData, rc); 1498 return rc; 1499 } 1500 1501 1502 /** 1503 * Shuts down a guest thread. 1504 * 1505 * @return IPRT status code. 1506 * @param pThread Thread to shut down. 1507 */ 1508 static int vboxServiceControlThreadShutdown(PVBOXSERVICECTRLTHREAD pThread) 1509 { 1510 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 1511 1512 int rc = RTCritSectEnter(&pThread->CritSect); 1513 if (RT_SUCCESS(rc)) 1514 { 1515 VBoxServiceVerbose(3, "ControlThead: [PID %u]: Shutting down ...\n", 1516 pThread->uPID); 1517 1518 /* 1519 * Destroy thread-specific data. 1520 */ 1521 vboxServiceControlThreadFree(pThread); 1522 1523 /* Set stopped status. */ 1524 ASMAtomicXchgBool(&pThread->fStopped, true); 1525 1526 rc = RTCritSectLeave(&pThread->CritSect); 1527 } 1528 1529 /* 1530 * Destroy other thread data. 1531 */ 1532 if (RTCritSectIsInitialized(&pThread->CritSect)) 1533 RTCritSectDelete(&pThread->CritSect); 1534 1535 /* 1536 * Destroy thread structure as final step. 1537 */ 1538 RTMemFree(pThread); 1539 pThread = NULL; 1540 1541 return rc; 1542 } 1543 1555 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Performed enmType=%u, uCID=%u, pvData=0x%p, cbData=%u, rc=%Rrc\n", 1556 uPID, pRequest->enmType, pRequest->uCID, pRequest->pvData, pRequest->cbData, rc); 1557 return rc; 1558 } 1559 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r39392 r39418 171 171 /** Payload data; a pre-allocated data buffer for input/output. */ 172 172 void *pvData; 173 /** The context ID which is required to complete the 174 * request. */ 175 uint32_t uCID; 173 176 /** The overall result of the operation. */ 174 177 int rc; … … 230 233 /** Pointer to thread data. */ 231 234 typedef VBOXSERVICECTRLTHREAD *PVBOXSERVICECTRLTHREAD; 235 236 /** 237 * Request types to perform on a started guest process. 238 */ 239 typedef enum VBOXSERVICECTRLTHREADSTATUS 240 { 241 /** Unknown status. Do not use / should not happen. */ 242 VBOXSERVICECTRLTHREADSTATUS_UNKNOWN = 0, 243 VBOXSERVICECTRLTHREADSTATUS_STARTED = 100, 244 VBOXSERVICECTRLTHREADSTATUS_STOPPED = 200 245 } VBOXSERVICECTRLTHREADSTATUS; 232 246 #endif /* VBOX_WITH_GUEST_CONTROL */ 233 247 #ifdef VBOX_WITH_GUEST_PROPS … … 329 343 extern int VBoxServiceControlHandleCmdSetInput(uint32_t u32ClientId, uint32_t uNumParms, size_t cbMaxBufSize); 330 344 extern int VBoxServiceControlHandleCmdGetOutput(uint32_t u32ClientId, uint32_t uNumParms); 331 extern PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadByPID(uint32_t uPID); 332 extern void VBoxServiceControlRemoveThread(PVBOXSERVICECTRLTHREAD pThread); 345 extern const PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadLocked(uint32_t uPID); 346 extern void VBoxServiceControlThreadUnlock(const PVBOXSERVICECTRLTHREAD pThread); 347 extern int VBoxServiceControlAssignPID(PVBOXSERVICECTRLTHREAD pThread, uint32_t uPID); 348 extern void VBoxServiceControlRemoveThread(const PVBOXSERVICECTRLTHREAD pThread); 333 349 /* Guest process functions. */ 350 extern VBOXSERVICECTRLTHREADSTATUS VBoxServiceControlThreadGetStatus(const PVBOXSERVICECTRLTHREAD pThread); 334 351 extern int VBoxServiceControlThreadStart(uint32_t uClientID, uint32_t uContext, 335 352 const char *pszCmd, uint32_t uFlags, … … 338 355 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS, 339 356 PRTLISTNODE *ppNode); 340 intVBoxServiceControlThreadPerform(uint32_t uPID, PVBOXSERVICECTRLREQUEST pRequest);357 extern int VBoxServiceControlThreadPerform(uint32_t uPID, PVBOXSERVICECTRLREQUEST pRequest); 341 358 extern int VBoxServiceControlThreadSignalShutdown(const PVBOXSERVICECTRLTHREAD pThread); 342 359 extern int VBoxServiceControlThreadWaitForShutdown(const PVBOXSERVICECTRLTHREAD pThread, RTMSINTERVAL msTimeout);
Note:
See TracChangeset
for help on using the changeset viewer.