Changeset 28402 in vbox for trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
- Timestamp:
- Apr 16, 2010 10:13:22 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlExec.cpp
r28347 r28402 50 50 using namespace guestControl; 51 51 52 extern GuestCtrlExecThreads g_GuestControlExecThreads; 53 52 54 /** 53 55 * Handle an error event on standard input. … … 235 237 236 238 237 static int VBoxServiceControlExecProcLoop(PVBOXSERVICECTRLTHREAD DATA pData,239 static int VBoxServiceControlExecProcLoop(PVBOXSERVICECTRLTHREAD pThread, 238 240 RTPROCESS hProcess, RTMSINTERVAL cMillies, RTPOLLSET hPollSet, 239 241 RTPIPE hStdInW, RTPIPE hStdOutR, RTPIPE hStdErrR) … … 258 260 259 261 /* Assign PID to thread data. */ 260 p Data->uPID = hProcess;262 pThread->uPID = hProcess; 261 263 262 264 /* … … 264 266 * and that it's now OK to send input to the process. 265 267 */ 266 AssertPtr(p Data);268 AssertPtr(pThread); 267 269 VBoxServiceVerbose(3, "Control: Process started: PID=%u, CID=%u\n", 268 p Data->uPID, pData->uContextID);269 rc = VbglR3GuestCtrlExecReportStatus(p Data->uClientID, pData->uContextID,270 p Data->uPID, PROC_STS_STARTED, 0 /* u32Flags */,270 pThread->uPID, pThread->uContextID); 271 rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID, 272 pThread->uPID, PROC_STS_STARTED, 0 /* u32Flags */, 271 273 NULL /* pvData */, 0 /* cbData */); 272 274 … … 274 276 * Process input, output, the test pipe and client requests. 275 277 */ 276 while (RT_SUCCESS(rc)) 278 while ( RT_SUCCESS(rc) 279 && RT_UNLIKELY(!pThread->fShutdown)) 277 280 { 278 281 /* … … 282 285 uint32_t fPollEvt; 283 286 rc2 = RTPollNoResume(hPollSet, cMsPollCur, &fPollEvt, &idPollHnd); 287 if (pThread->fShutdown) 288 continue; 284 289 285 290 cMsPollCur = 0; /* no rest until we've checked everything. */ … … 376 381 /* Reset the polling interval since we've done all pending work. */ 377 382 cMsPollCur = cMilliesLeft >= cMsPollBase ? cMsPollBase : cMilliesLeft; 383 384 /* 385 * Need to exit? 386 */ 387 if (pThread->fShutdown) 388 break; 378 389 } 379 390 … … 421 432 uStatus = PROC_STS_TOA; 422 433 } 423 /*else if (g_fTerminate&& (fProcessAlive || MsProcessKilled != UINT64_MAX))424 { 425 uStatus = PROC_STS_DWN; 426 } */434 else if (pThread->fShutdown && (fProcessAlive || MsProcessKilled != UINT64_MAX)) 435 { 436 uStatus = PROC_STS_DWN; /* Service is stopping, process was killed. */ 437 } 427 438 else if (fProcessAlive) 428 439 { … … 454 465 455 466 VBoxServiceVerbose(3, "Control: Process ended: PID=%u, CID=%u, Status=%u, Flags=%u\n", 456 p Data->uPID, pData->uContextID, uStatus, uFlags);457 rc = VbglR3GuestCtrlExecReportStatus(p Data->uClientID, pData->uContextID,458 p Data->uPID, uStatus, uFlags,467 pThread->uPID, pThread->uContextID, uStatus, uFlags); 468 rc = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID, 469 pThread->uPID, uStatus, uFlags, 459 470 NULL /* pvData */, 0 /* cbData */); 460 471 } … … 517 528 518 529 /** Allocates and gives back a thread data struct which then can be used by the worker thread. */ 519 PVBOXSERVICECTRLTHREAD DATAVBoxServiceControlExecAllocateThreadData(uint32_t u32ContextID,520 521 522 523 524 525 { 526 PVBOXSERVICECTRLTHREAD DATA pData = (PVBOXSERVICECTRLTHREADDATA)RTMemAlloc(sizeof(VBOXSERVICECTRLTHREADDATA));527 if (p Data== NULL)530 PVBOXSERVICECTRLTHREAD VBoxServiceControlExecAllocateThreadData(uint32_t u32ContextID, 531 const char *pszCmd, uint32_t uFlags, 532 const char *pszArgs, uint32_t uNumArgs, 533 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars, 534 const char *pszStdIn, const char *pszStdOut, const char *pszStdErr, 535 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS) 536 { 537 PVBOXSERVICECTRLTHREAD pThread = (PVBOXSERVICECTRLTHREAD)RTMemAlloc(sizeof(VBOXSERVICECTRLTHREAD)); 538 if (pThread == NULL) 528 539 return NULL; 529 540 541 pThread->fShutdown = false; 542 pThread->fStarted = false; 543 pThread->fStopped = false; 544 530 545 /* ClientID will be assigned when thread is started! */ 531 p Data->uContextID = u32ContextID;532 p Data->uPID = 0; /* Don't have a PID yet. */533 p Data->pszCmd = RTStrDup(pszCmd);534 p Data->uFlags = uFlags;535 p Data->uNumEnvVars = 0;536 p Data->uNumArgs = 0; /* Initialize in case of RTGetOptArgvFromString() is failing ... */546 pThread->uContextID = u32ContextID; 547 pThread->uPID = 0; /* Don't have a PID yet. */ 548 pThread->pszCmd = RTStrDup(pszCmd); 549 pThread->uFlags = uFlags; 550 pThread->uNumEnvVars = 0; 551 pThread->uNumArgs = 0; /* Initialize in case of RTGetOptArgvFromString() is failing ... */ 537 552 538 553 /* Prepare argument list. */ 539 int rc = RTGetOptArgvFromString(&p Data->papszArgs, (int*)&pData->uNumArgs,554 int rc = RTGetOptArgvFromString(&pThread->papszArgs, (int*)&pThread->uNumArgs, 540 555 (uNumArgs > 0) ? pszArgs : "", NULL); 541 556 /* Did we get the same result? */ 542 Assert(uNumArgs == p Data->uNumArgs);557 Assert(uNumArgs == pThread->uNumArgs); 543 558 544 559 if (RT_SUCCESS(rc)) … … 547 562 if (uNumEnvVars) 548 563 { 549 p Data->papszEnv = (char**)RTMemAlloc(uNumEnvVars * sizeof(char*));550 AssertPtr(p Data->papszEnv);551 p Data->uNumEnvVars = uNumEnvVars;564 pThread->papszEnv = (char**)RTMemAlloc(uNumEnvVars * sizeof(char*)); 565 AssertPtr(pThread->papszEnv); 566 pThread->uNumEnvVars = uNumEnvVars; 552 567 553 568 const char *pcCur = pszEnv; … … 556 571 while (cbLen < cbEnv) 557 572 { 558 if (RTStrAPrintf(& p Data->papszEnv[i++], "%s", pcCur) < 0)573 if (RTStrAPrintf(& pThread->papszEnv[i++], "%s", pcCur) < 0) 559 574 { 560 575 rc = VERR_NO_MEMORY; … … 566 581 } 567 582 568 p Data->pszStdIn = RTStrDup(pszStdIn);569 p Data->pszStdOut = RTStrDup(pszStdOut);570 p Data->pszStdErr = RTStrDup(pszStdErr);571 p Data->pszUser = RTStrDup(pszUser);572 p Data->pszPassword = RTStrDup(pszPassword);573 p Data->uTimeLimitMS = uTimeLimitMS;583 pThread->pszStdIn = RTStrDup(pszStdIn); 584 pThread->pszStdOut = RTStrDup(pszStdOut); 585 pThread->pszStdErr = RTStrDup(pszStdErr); 586 pThread->pszUser = RTStrDup(pszUser); 587 pThread->pszPassword = RTStrDup(pszPassword); 588 pThread->uTimeLimitMS = uTimeLimitMS; 574 589 } 575 590 576 591 /* Adjust time limit value. */ 577 p Data->uTimeLimitMS = ( (uTimeLimitMS == UINT32_MAX)578 || (uTimeLimitMS == 0)) ?579 RT_INDEFINITE_WAIT : uTimeLimitMS;580 return p Data;592 pThread->uTimeLimitMS = ( (uTimeLimitMS == UINT32_MAX) 593 || (uTimeLimitMS == 0)) ? 594 RT_INDEFINITE_WAIT : uTimeLimitMS; 595 return pThread; 581 596 } 582 597 583 598 /** Frees an allocated thread data structure along with all its allocated parameters. */ 584 void VBoxServiceControlExecFreeThreadData(PVBOXSERVICECTRLTHREADDATA pData) 585 { 586 AssertPtr(pData); 587 RTStrFree(pData->pszCmd); 588 if (pData->uNumEnvVars) 589 { 590 for (uint32_t i = 0; i < pData->uNumEnvVars; i++) 591 RTStrFree(pData->papszEnv[i]); 592 RTMemFree(pData->papszEnv); 593 } 594 RTGetOptArgvFree(pData->papszArgs); 595 RTStrFree(pData->pszStdIn); 596 RTStrFree(pData->pszStdOut); 597 RTStrFree(pData->pszStdErr); 598 RTStrFree(pData->pszUser); 599 RTStrFree(pData->pszPassword); 600 601 RTMemFree(pData); 602 } 603 604 DECLCALLBACK(int) VBoxServiceControlExecProcessWorker(PVBOXSERVICECTRLTHREADDATA pData) 605 { 606 AssertPtr(pData); 607 AssertPtr(pData->papszArgs); 608 AssertPtr(pData->papszEnv); 599 void VBoxServiceControlExecDestroyThread(PVBOXSERVICECTRLTHREAD pThread) 600 { 601 AssertPtr(pThread); 602 RTStrFree(pThread->pszCmd); 603 if (pThread->uNumEnvVars) 604 { 605 for (uint32_t i = 0; i < pThread->uNumEnvVars; i++) 606 RTStrFree(pThread->papszEnv[i]); 607 RTMemFree(pThread->papszEnv); 608 } 609 RTGetOptArgvFree(pThread->papszArgs); 610 RTStrFree(pThread->pszStdIn); 611 RTStrFree(pThread->pszStdOut); 612 RTStrFree(pThread->pszStdErr); 613 RTStrFree(pThread->pszUser); 614 RTStrFree(pThread->pszPassword); 615 616 RTMemFree(pThread); 617 } 618 619 DECLCALLBACK(int) VBoxServiceControlExecProcessWorker(PVBOXSERVICECTRLTHREAD pThread) 620 { 621 AssertPtr(pThread); 622 623 AssertPtr(pThread); 624 AssertPtr(pThread->papszArgs); 625 AssertPtr(pThread->papszEnv); 609 626 610 627 /* … … 613 630 */ 614 631 RTThreadUserSignal(RTThreadSelf()); 615 VBoxServiceVerbose(3, "Control: Thread of process \"%s\" started\n", p Data->pszCmd);616 617 int rc = VbglR3GuestCtrlConnect(&p Data->uClientID);632 VBoxServiceVerbose(3, "Control: Thread of process \"%s\" started\n", pThread->pszCmd); 633 634 int rc = VbglR3GuestCtrlConnect(&pThread->uClientID); 618 635 if (RT_FAILURE(rc)) 619 636 { … … 630 647 { 631 648 size_t i; 632 for (i = 0; i < p Data->uNumEnvVars; i++)633 { 634 rc = RTEnvPutEx(hEnv, p Data->papszEnv[i]);649 for (i = 0; i < pThread->uNumEnvVars; i++) 650 { 651 rc = RTEnvPutEx(hEnv, pThread->papszEnv[i]); 635 652 if (RT_FAILURE(rc)) 636 653 break; … … 676 693 { 677 694 RTPROCESS hProcess; 678 rc = RTProcCreateEx(p Data->pszCmd, pData->papszArgs, hEnv, pData->uFlags,695 rc = RTProcCreateEx(pThread->pszCmd, pThread->papszArgs, hEnv, pThread->uFlags, 679 696 phStdIn, phStdOut, phStdErr, 680 strlen(p Data->pszUser) ? pData->pszUser : NULL,681 strlen(p Data->pszUser) && strlen(pData->pszPassword) ? pData->pszPassword : NULL,697 strlen(pThread->pszUser) ? pThread->pszUser : NULL, 698 strlen(pThread->pszUser) && strlen(pThread->pszPassword) ? pThread->pszPassword : NULL, 682 699 &hProcess); 683 700 if (RT_SUCCESS(rc)) … … 694 711 695 712 /* Enter the process loop. */ 696 rc = VBoxServiceControlExecProcLoop(p Data,697 hProcess, p Data->uTimeLimitMS, hPollSet,713 rc = VBoxServiceControlExecProcLoop(pThread, 714 hProcess, pThread->uTimeLimitMS, hPollSet, 698 715 hStdInW, hStdOutR, hStdErrR); 699 716 … … 713 730 else /* Something went wrong; report error! */ 714 731 { 715 int rc2 = VbglR3GuestCtrlExecReportStatus(p Data->uClientID, pData->uContextID, pData->uPID,732 int rc2 = VbglR3GuestCtrlExecReportStatus(pThread->uClientID, pThread->uContextID, pThread->uPID, 716 733 PROC_STS_ERROR, rc, 717 734 NULL /* pvData */, 0 /* cbData */); … … 735 752 } 736 753 737 VbglR3GuestCtrlDisconnect(p Data->uClientID);754 VbglR3GuestCtrlDisconnect(pThread->uClientID); 738 755 VBoxServiceVerbose(3, "Control: Thread of process \"%s\" (PID: %u) ended with rc=%Rrc\n", 739 pData->pszCmd, pData->uPID, rc); 740 741 /* 742 * Since we (hopefully) are the only ones that hold the thread data, 743 * destroy them now. 744 */ 745 VBoxServiceControlExecFreeThreadData(pData); 756 pThread->pszCmd, pThread->uPID, rc); 746 757 return rc; 747 758 } … … 749 760 static DECLCALLBACK(int) VBoxServiceControlExecThread(RTTHREAD ThreadSelf, void *pvUser) 750 761 { 751 PVBOXSERVICECTRLTHREADDATA pData = (PVBOXSERVICECTRLTHREADDATA)pvUser; 752 return VBoxServiceControlExecProcessWorker(pData); 762 PVBOXSERVICECTRLTHREAD pThread = (VBOXSERVICECTRLTHREAD*)pvUser; 763 AssertPtr(pThread); 764 return VBoxServiceControlExecProcessWorker(pThread); 753 765 } 754 766 … … 759 771 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS) 760 772 { 761 PVBOXSERVICECTRLTHREAD DATA pThreadData=773 PVBOXSERVICECTRLTHREAD pThread = 762 774 VBoxServiceControlExecAllocateThreadData(uContextID, 763 775 pszCmd, uFlags, … … 768 780 uTimeLimitMS); 769 781 int rc = VINF_SUCCESS; 770 if (pThread Data)771 { 772 rc = RTThreadCreate( NULL, VBoxServiceControlExecThread,773 (void *)(PVBOXSERVICECTRLTHREADDATA)pThreadData, 0,774 782 if (pThread) 783 { 784 rc = RTThreadCreate(&pThread->Thread, VBoxServiceControlExecThread, 785 (void *)(PVBOXSERVICECTRLTHREAD*)pThread, 0, 786 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Exec"); 775 787 if (RT_FAILURE(rc)) 776 788 { 777 VBoxServiceError("Control: RTThreadCreate failed, rc=%Rrc\n, threadData=%p\n", 778 rc, pThreadData); 789 VBoxServiceError("Control: RTThreadCreate failed, rc=%Rrc\n, pThread=%p\n", 790 rc, pThread); 791 } 792 else 793 { 794 /* Wait for the thread to initialize. */ 795 RTThreadUserWait(pThread->Thread, 60 * 1000); 796 if (pThread->fShutdown) 797 { 798 VBoxServiceError("Control: Thread for process \"%s\" failed to start!\n", pszCmd); 799 rc = VERR_GENERAL_FAILURE; 800 } 801 else 802 { 803 g_GuestControlExecThreads.push_back(pThread); 804 } 805 } 806 807 if (RT_FAILURE(rc)) 808 { 779 809 /* Only destroy thread data on failure; otherwise it's destroyed in the thread handler. */ 780 VBoxServiceControlExec FreeThreadData(pThreadData);810 VBoxServiceControlExecDestroyThread(pThread); 781 811 } 782 812 }
Note:
See TracChangeset
for help on using the changeset viewer.