Changeset 39906 in vbox for trunk/src/VBox
- Timestamp:
- Jan 30, 2012 12:50:03 PM (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
r39874 r39906 46 46 * the maximum number of processes is unlimited. */ 47 47 static uint32_t g_GuestControlProcsMaxKept = 25; 48 /** List of guest control threads (VBOXSERVICECTRLTHREAD). */ 49 static RTLISTANCHOR g_GuestControlThreads; 48 /** List of active guest control threads (VBOXSERVICECTRLTHREAD). */ 49 static RTLISTANCHOR g_GuestControlThreadsActive; 50 /** List of inactive guest control threads (VBOXSERVICECTRLTHREAD). */ 51 static RTLISTANCHOR g_GuestControlThreadsInactive; 50 52 /** Critical section protecting g_GuestControlExecThreads. */ 51 53 static RTCRITSECT g_GuestControlThreadsCritSect; … … 56 58 *******************************************************************************/ 57 59 /** @todo Shorten "VBoxServiceControl" to "gstsvcCntl". */ 60 static int VBoxServiceControlReapThreads(void); 58 61 static int VBoxServiceControlStartAllowed(bool *pbAllowed); 59 62 static int VBoxServiceControlHandleCmdStartProc(uint32_t u32ClientId, uint32_t uNumParms); … … 135 138 VBoxServiceVerbose(3, "Control: Service client ID: %#x\n", g_GuestControlSvcClientID); 136 139 137 /* Init thread list. */ 138 RTListInit(&g_GuestControlThreads); 140 /* Init thread lists. */ 141 RTListInit(&g_GuestControlThreadsActive); 142 RTListInit(&g_GuestControlThreadsInactive); 143 144 /* Init critical section for protecting the thread lists. */ 139 145 rc = RTCritSectInit(&g_GuestControlThreadsCritSect); 140 146 AssertRC(rc); … … 237 243 * 238 244 * @returns IPRT status code. 239 * @param idClientThe HGCM client session ID.245 * @param uClientID The HGCM client session ID. 240 246 * @param cParms The number of parameters the host is offering. 241 247 */ 242 static int VBoxServiceControlHandleCmdStartProc(uint32_t idClient, uint32_t cParms) 243 { 244 uint32_t uContextID; 245 char szCmd[_1K]; 246 uint32_t uFlags; 247 char szArgs[_1K]; 248 uint32_t cArgs; 249 char szEnv[_64K]; 250 uint32_t cbEnv = sizeof(szEnv); 251 uint32_t cEnvVars; 252 char szUser[128]; 253 char szPassword[128]; 254 uint32_t uTimeLimitMS; 255 256 #if 0 /* for valgrind */ 257 RT_ZERO(szCmd); 258 RT_ZERO(szArgs); 259 RT_ZERO(szEnv); 260 RT_ZERO(szUser); 261 RT_ZERO(szPassword); 262 #endif 248 static int VBoxServiceControlHandleCmdStartProc(uint32_t uClientID, uint32_t cParms) 249 { 250 uint32_t uContextID = 0; 263 251 264 252 int rc; … … 266 254 if (cParms == 11) 267 255 { 268 rc = VbglR3GuestCtrlExecGetHostCmdExec(idClient, 256 VBOXSERVICECTRLPROCESS proc; 257 RT_ZERO(proc); 258 259 rc = VbglR3GuestCtrlExecGetHostCmdExec(uClientID, 269 260 cParms, 270 261 &uContextID, 271 262 /* Command */ 272 szCmd, sizeof(szCmd),263 proc.szCmd, sizeof(proc.szCmd), 273 264 /* Flags */ 274 & uFlags,265 &proc.uFlags, 275 266 /* Arguments */ 276 szArgs, sizeof(szArgs), &cArgs,267 proc.szArgs, sizeof(proc.szArgs), &proc.uNumArgs, 277 268 /* Environment */ 278 szEnv, &cbEnv, &cEnvVars,269 proc.szEnv, &proc.cbEnv, &proc.uNumEnvVars, 279 270 /* Credentials */ 280 szUser, sizeof(szUser),281 szPassword, sizeof(szPassword),271 proc.szUser, sizeof(proc.szUser), 272 proc.szPassword, sizeof(proc.szPassword), 282 273 /* Timelimit */ 283 & uTimeLimitMS);274 &proc.uTimeLimitMS); 284 275 if (RT_SUCCESS(rc)) 285 276 { 286 277 VBoxServiceVerbose(3, "Control: Request to start process szCmd=%s, uFlags=0x%x, szArgs=%s, szEnv=%s, szUser=%s, uTimeout=%u\n", 287 szCmd, uFlags, cArgs ? szArgs : "<None>", cEnvVars ? szEnv : "<None>", szUser, uTimeLimitMS); 278 proc.szCmd, proc.uFlags, 279 proc.uNumArgs ? proc.szArgs : "<None>", 280 proc.uNumEnvVars ? proc.szEnv : "<None>", 281 proc.szUser, proc.uTimeLimitMS); 282 283 rc = VBoxServiceControlReapThreads(); 284 if (RT_FAILURE(rc)) 285 VBoxServiceError("Control: Reaping stopped processes failed with rc=%Rrc\n", rc); 286 /* Keep going. */ 287 288 288 rc = VBoxServiceControlStartAllowed(&fStartAllowed); 289 289 if (RT_SUCCESS(rc)) … … 291 291 if (fStartAllowed) 292 292 { 293 rc = RTCritSectEnter(&g_GuestControlThreadsCritSect); 294 if (RT_SUCCESS(rc)) 295 { 296 /** @todo Put the following params into a struct! */ 297 PRTLISTNODE pThreadNode; 298 rc = VBoxServiceControlThreadStart(idClient, uContextID, 299 szCmd, uFlags, szArgs, cArgs, 300 szEnv, cbEnv, cEnvVars, 301 szUser, szPassword, uTimeLimitMS, 302 &pThreadNode); 303 if (RT_SUCCESS(rc)) 304 { 305 /* Insert thread node into thread list. */ 306 /*rc =*/ RTListAppend(&g_GuestControlThreads, pThreadNode); 307 } 308 309 int rc2 = RTCritSectLeave(&g_GuestControlThreadsCritSect); 310 if (RT_SUCCESS(rc)) 311 rc = rc2; 312 } 293 rc = VBoxServiceControlThreadStart(uContextID, &proc); 313 294 } 314 295 else … … 325 306 VBoxServiceError("Control: Starting process failed with rc=%Rrc\n", rc); 326 307 327 int rc2 = VbglR3GuestCtrlExecReportStatus( idClient, uContextID, 0 /* PID, invalid. */,308 int rc2 = VbglR3GuestCtrlExecReportStatus(uClientID, uContextID, 0 /* PID, invalid. */, 328 309 PROC_STS_ERROR, rc, 329 310 NULL /* pvData */, 0 /* cbData */); … … 399 380 400 381 /** 382 * Sets the specified guest thread to a certain list. 383 * 384 * @return IPRT status code. 385 * @param enmList List to move thread to. 386 * @param pThread Thread to set inactive. 387 */ 388 int VBoxServiceControlListSet(VBOXSERVICECTRLTHREADLISTTYPE enmList, 389 PVBOXSERVICECTRLTHREAD pThread) 390 { 391 AssertReturn(enmList > VBOXSERVICECTRLTHREADLIST_UNKNOWN, VERR_INVALID_PARAMETER); 392 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 393 394 int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect); 395 if (RT_SUCCESS(rc)) 396 { 397 VBoxServiceVerbose(3, "Control: Setting thread (PID %u) inactive\n", 398 pThread->uPID); 399 400 PRTLISTANCHOR pAnchor = NULL; 401 switch (enmList) 402 { 403 case VBOXSERVICECTRLTHREADLIST_STOPPED: 404 pAnchor = &g_GuestControlThreadsInactive; 405 break; 406 407 case VBOXSERVICECTRLTHREADLIST_RUNNING: 408 pAnchor = &g_GuestControlThreadsActive; 409 break; 410 411 default: 412 AssertMsgFailed(("Unknown list type: %u", enmList)); 413 break; 414 } 415 416 if (!pAnchor) 417 rc = VERR_INVALID_PARAMETER; 418 419 if (RT_SUCCESS(rc)) 420 { 421 if (pThread->pAnchor != NULL) 422 { 423 /* If thread was assigned to a list before, 424 * remove the thread from the old list first. */ 425 /* rc = */ RTListNodeRemove(&pThread->Node); 426 } 427 428 /* Add thread to desired list. */ 429 /* rc = */ RTListAppend(pAnchor, &pThread->Node); 430 pThread->pAnchor = pAnchor; 431 } 432 433 int rc2 = RTCritSectLeave(&g_GuestControlThreadsCritSect); 434 if (RT_SUCCESS(rc)) 435 rc = rc2; 436 } 437 438 return VINF_SUCCESS; 439 } 440 441 442 /** 401 443 * Injects input to a specified running process. 402 444 * … … 413 455 uint32_t *pcbWritten) 414 456 { 415 AssertPtrReturn(pvBuf, VERR_INVALID_PARAMETER);416 AssertReturn(cbBuf, VERR_INVALID_PARAMETER);457 /* pvBuf is optional. */ 458 /* cbBuf is optional. */ 417 459 /* pcbWritten is optional. */ 418 460 … … 474 516 uPID, rc); 475 517 } 476 else if (cbSize > 518 else if (cbSize > cbMaxBufSize) 477 519 { 478 520 VBoxServiceError("Control: [PID %u]: Too much input received! cbSize=%u, cbMaxBufSize=%u\n", … … 623 665 624 666 /** 667 * Reaps all inactive guest process threads. 668 * 669 * @return IPRT status code. 670 */ 671 static int VBoxServiceControlReapThreads(void) 672 { 673 int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect); 674 if (RT_SUCCESS(rc)) 675 { 676 PVBOXSERVICECTRLTHREAD pThread = 677 RTListGetFirst(&g_GuestControlThreadsInactive, VBOXSERVICECTRLTHREAD, Node); 678 while (pThread) 679 { 680 PVBOXSERVICECTRLTHREAD pNext = RTListNodeGetNext(&pThread->Node, VBOXSERVICECTRLTHREAD, Node); 681 bool fLast = RTListNodeIsLast(&g_GuestControlThreadsInactive, &pThread->Node); 682 683 int rc2 = VBoxServiceControlThreadWait(pThread, 30 * 1000 /* 30 seconds max. */); 684 if (RT_SUCCESS(rc2)) 685 { 686 RTListNodeRemove(&pThread->Node); 687 688 rc2 = VBoxServiceControlThreadFree(pThread); 689 if (RT_FAILURE(rc2)) 690 { 691 VBoxServiceError("Control: Stopping guest process thread failed with rc=%Rrc\n", rc2); 692 if (RT_SUCCESS(rc)) /* Keep original failure. */ 693 rc = rc2; 694 } 695 } 696 else 697 VBoxServiceError("Control: Waiting on guest process thread failed with rc=%Rrc\n", rc2); 698 /* Keep going. */ 699 700 if (fLast) 701 break; 702 703 pThread = pNext; 704 } 705 706 int rc2 = RTCritSectLeave(&g_GuestControlThreadsCritSect); 707 if (RT_SUCCESS(rc)) 708 rc = rc2; 709 } 710 711 VBoxServiceVerbose(4, "Control: Reaping threads returned with rc=%Rrc\n", rc); 712 return rc; 713 } 714 715 716 /** 625 717 * Destroys all guest process threads which are still active. 626 718 */ 627 static void VBoxServiceControl DestroyThreads(void)628 { 629 VBoxServiceVerbose(2, "Control: Destroying threads...\n");630 631 /* Signal all threads that we want to shutdown. */719 static void VBoxServiceControlShutdown(void) 720 { 721 VBoxServiceVerbose(2, "Control: Shutting down ...\n"); 722 723 /* Signal all threads in the active list that we want to shutdown. */ 632 724 PVBOXSERVICECTRLTHREAD pThread; 633 RTListForEach(&g_GuestControlThreads , pThread, VBOXSERVICECTRLTHREAD, Node)634 VBoxServiceControlThreadS ignalShutdown(pThread);635 636 /* Wait for threads to shutdown and destroythread list. */637 pThread = RTListGetFirst(&g_GuestControlThreads , VBOXSERVICECTRLTHREAD, Node);725 RTListForEach(&g_GuestControlThreadsActive, pThread, VBOXSERVICECTRLTHREAD, Node) 726 VBoxServiceControlThreadStop(pThread); 727 728 /* Wait for all active threads to shutdown and destroy the active thread list. */ 729 pThread = RTListGetFirst(&g_GuestControlThreadsActive, VBOXSERVICECTRLTHREAD, Node); 638 730 while (pThread) 639 731 { 640 732 PVBOXSERVICECTRLTHREAD pNext = RTListNodeGetNext(&pThread->Node, VBOXSERVICECTRLTHREAD, Node); 641 bool fLast = RTListNodeIsLast(&g_GuestControlThreads , &pThread->Node);642 643 int rc2 = VBoxServiceControlThreadWait ForShutdown(pThread,644 733 bool fLast = RTListNodeIsLast(&g_GuestControlThreadsActive, &pThread->Node); 734 735 int rc2 = VBoxServiceControlThreadWait(pThread, 736 30 * 1000 /* Wait 30 seconds max. */); 645 737 if (RT_FAILURE(rc2)) 646 738 VBoxServiceError("Control: Guest process thread failed to stop; rc=%Rrc\n", rc2); … … 652 744 } 653 745 654 #ifdef DEBUG 655 PVBOXSERVICECTRLTHREAD pThreadCur; 656 uint32_t cThreads = 0; 657 RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node) 658 cThreads++; 659 VBoxServiceVerbose(4, "Control: Guest process threads left=%u\n", cThreads); 660 #endif 661 AssertMsg(RTListIsEmpty(&g_GuestControlThreads), 662 ("Guest process thread list still contains children when it should not\n")); 746 int rc2 = VBoxServiceControlReapThreads(); 747 if (RT_FAILURE(rc2)) 748 VBoxServiceError("Control: Reaping inactive threads failed with rc=%Rrc\n", rc2); 749 750 AssertMsg(RTListIsEmpty(&g_GuestControlThreadsActive), 751 ("Guest process active thread list still contains entries when it should not\n")); 752 AssertMsg(RTListIsEmpty(&g_GuestControlThreadsInactive), 753 ("Guest process inactive thread list still contains entries when it should not\n")); 663 754 664 755 /* Destroy critical section. */ 665 756 RTCritSectDelete(&g_GuestControlThreadsCritSect); 757 758 VBoxServiceVerbose(2, "Control: Shutting down complete\n"); 666 759 } 667 760 … … 672 765 VBoxServiceVerbose(3, "Control: Terminating ...\n"); 673 766 674 VBoxServiceControl DestroyThreads();767 VBoxServiceControlShutdown(); 675 768 676 769 VBoxServiceVerbose(3, "Control: Disconnecting client ID=%u ...\n", … … 710 803 { 711 804 uint32_t uProcsRunning = 0; 712 uint32_t uProcsStopped = 0;713 805 PVBOXSERVICECTRLTHREAD pThread; 714 RTListForEach(&g_GuestControlThreads, pThread, VBOXSERVICECTRLTHREAD, Node) 715 { 716 VBoxServiceControlThreadActive(pThread) 717 ? uProcsRunning++ 718 : uProcsStopped++; 719 } 720 721 VBoxServiceVerbose(3, "Control: Maximum served guest processes set to %u, running=%u, stopped=%u\n", 722 g_GuestControlProcsMaxKept, uProcsRunning, uProcsStopped); 806 RTListForEach(&g_GuestControlThreadsActive, pThread, VBOXSERVICECTRLTHREAD, Node) 807 uProcsRunning++; 808 809 VBoxServiceVerbose(3, "Control: Maximum served guest processes set to %u, running=%u\n", 810 g_GuestControlProcsMaxKept, uProcsRunning); 723 811 724 812 int32_t iProcsLeft = (g_GuestControlProcsMaxKept - uProcsRunning - 1); … … 749 837 * @param uPID PID to search for. 750 838 */ 751 PVBOXSERVICECTRLTHREAD VBoxServiceControl GetThreadLocked(uint32_t uPID)839 PVBOXSERVICECTRLTHREAD VBoxServiceControlLockThread(uint32_t uPID) 752 840 { 753 841 PVBOXSERVICECTRLTHREAD pThread = NULL; … … 756 844 { 757 845 PVBOXSERVICECTRLTHREAD pThreadCur; 758 RTListForEach(&g_GuestControlThreads , pThreadCur, VBOXSERVICECTRLTHREAD, Node)846 RTListForEach(&g_GuestControlThreadsActive, pThreadCur, VBOXSERVICECTRLTHREAD, Node) 759 847 { 760 848 if (pThreadCur->uPID == uPID) … … 781 869 * @param pThread Thread to unlock. 782 870 */ 783 void VBoxServiceControl ThreadUnlock(const PVBOXSERVICECTRLTHREAD pThread)871 void VBoxServiceControlUnlockThread(const PVBOXSERVICECTRLTHREAD pThread) 784 872 { 785 873 AssertPtr(pThread); … … 812 900 do 813 901 { 814 RTListForEach(&g_GuestControlThreads , pThreadCur, VBOXSERVICECTRLTHREAD, Node)902 RTListForEach(&g_GuestControlThreadsActive, pThreadCur, VBOXSERVICECTRLTHREAD, Node) 815 903 { 816 904 if (pThreadCur->uPID == uPID) … … 835 923 836 924 return rc; 837 }838 839 840 /**841 * Removes the specified guest process thread from the global thread842 * list.843 *844 * @return IPRT status code.845 * @param pThread Thread to remove.846 */847 void VBoxServiceControlRemoveThread(const PVBOXSERVICECTRLTHREAD pThread)848 {849 if (!pThread)850 return;851 852 int rc = RTCritSectEnter(&g_GuestControlThreadsCritSect);853 if (RT_SUCCESS(rc))854 {855 VBoxServiceVerbose(4, "Control: Removing thread (PID: %u) from thread list\n",856 pThread->uPID);857 RTListNodeRemove(&pThread->Node);858 859 #ifdef DEBUG860 PVBOXSERVICECTRLTHREAD pThreadCur;861 uint32_t cThreads = 0;862 RTListForEach(&g_GuestControlThreads, pThreadCur, VBOXSERVICECTRLTHREAD, Node)863 cThreads++;864 VBoxServiceVerbose(4, "Control: Guest process threads left=%u\n", cThreads);865 #endif866 rc = RTCritSectLeave(&g_GuestControlThreadsCritSect);867 AssertRC(rc);868 }869 925 } 870 926 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlThread.cpp
r39896 r39906 43 43 44 44 /* Internal functions. */ 45 static int vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread);46 45 static int vboxServiceControlThreadRequestCancel(PVBOXSERVICECTRLREQUEST pThread); 47 46 … … 52 51 * @param pThread The thread's handle to allocate the data for. 53 52 * @param u32ContextID The context ID bound to this request / command. 54 * @param pszCmd Full qualified path of process to start (without arguments). 55 * @param uFlags Process execution flags. 56 * @param pszArgs String of arguments to pass to the process to start. 57 * @param uNumArgs Number of arguments specified in pszArgs. 58 * @param pszEnv String of environment variables ("FOO=BAR") to pass to the process 59 * to start. 60 * @param cbEnv Size (in bytes) of environment variables. 61 * @param uNumEnvVars Number of environment variables specified in pszEnv. 62 * @param pszUser User name (account) to start the process under. 63 * @param pszPassword Password of specified user name (account). 64 * @param uTimeLimitMS Time limit (in ms) of the process' life time. 53 @ @param pProcess Process information. 65 54 */ 66 55 static int gstsvcCntlExecThreadInit(PVBOXSERVICECTRLTHREAD pThread, 67 uint32_t u32ContextID, 68 const char *pszCmd, uint32_t uFlags, 69 const char *pszArgs, uint32_t uNumArgs, 70 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars, 71 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS) 56 PVBOXSERVICECTRLPROCESS pProcess, 57 uint32_t u32ContextID) 72 58 { 73 59 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 60 AssertPtrReturn(pProcess, VERR_INVALID_POINTER); 74 61 75 62 /* General stuff. */ 63 pThread->pAnchor = NULL; 76 64 pThread->Node.pPrev = NULL; 77 65 pThread->Node.pNext = NULL; … … 92 80 pThread->uPID = 0; /* Don't have a PID yet. */ 93 81 pThread->pRequest = NULL; /* No request assigned yet. */ 94 pThread->uFlags = uFlags;95 pThread->uTimeLimitMS = ( uTimeLimitMS == UINT32_MAX96 || uTimeLimitMS == 0)97 ? RT_INDEFINITE_WAIT : uTimeLimitMS;82 pThread->uFlags = pProcess->uFlags; 83 pThread->uTimeLimitMS = ( pProcess->uTimeLimitMS == UINT32_MAX 84 || pProcess->uTimeLimitMS == 0) 85 ? RT_INDEFINITE_WAIT : pProcess->uTimeLimitMS; 98 86 99 87 /* Prepare argument list. */ 100 88 pThread->uNumArgs = 0; /* Initialize in case of RTGetOptArgvFromString() is failing ... */ 101 89 rc = RTGetOptArgvFromString(&pThread->papszArgs, (int*)&pThread->uNumArgs, 102 ( uNumArgs > 0) ? pszArgs : "", NULL);90 (pProcess->uNumArgs > 0) ? pProcess->szArgs : "", NULL); 103 91 /* Did we get the same result? */ 104 Assert( uNumArgs == pThread->uNumArgs);92 Assert(pProcess->uNumArgs == pThread->uNumArgs); 105 93 106 94 if (RT_SUCCESS(rc)) … … 108 96 /* Prepare environment list. */ 109 97 pThread->uNumEnvVars = 0; 110 if ( uNumEnvVars)111 { 112 pThread->papszEnv = (char **)RTMemAlloc( uNumEnvVars * sizeof(char*));98 if (pProcess->uNumEnvVars) 99 { 100 pThread->papszEnv = (char **)RTMemAlloc(pProcess->uNumEnvVars * sizeof(char*)); 113 101 AssertPtr(pThread->papszEnv); 114 pThread->uNumEnvVars = uNumEnvVars;115 116 const char *pszCur = p szEnv;102 pThread->uNumEnvVars = pProcess->uNumEnvVars; 103 104 const char *pszCur = pProcess->szEnv; 117 105 uint32_t i = 0; 118 106 uint32_t cbLen = 0; 119 while (cbLen < cbEnv)107 while (cbLen < pProcess->cbEnv) 120 108 { 121 109 /* sanity check */ 122 if (i >= uNumEnvVars)110 if (i >= pProcess->uNumEnvVars) 123 111 { 124 112 rc = VERR_INVALID_PARAMETER; … … 138 126 139 127 /* The actual command to execute. */ 140 pThread->pszCmd = RTStrDup(p szCmd);128 pThread->pszCmd = RTStrDup(pProcess->szCmd); 141 129 AssertPtr(pThread->pszCmd); 142 130 143 131 /* User management. */ 144 pThread->pszUser = RTStrDup(p szUser);132 pThread->pszUser = RTStrDup(pProcess->szUser); 145 133 AssertPtr(pThread->pszUser); 146 pThread->pszPassword = RTStrDup(p szPassword);134 pThread->pszPassword = RTStrDup(pProcess->szPassword); 147 135 AssertPtr(pThread->pszPassword); 148 136 } 149 137 150 138 if (RT_FAILURE(rc)) /* Clean up on failure. */ 151 vboxServiceControlThreadFree(pThread);139 VBoxServiceControlThreadFree(pThread); 152 140 return rc; 153 141 } … … 160 148 * @param pThread Thread to shut down. 161 149 */ 162 static int vboxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread)150 int VBoxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread) 163 151 { 164 152 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 165 153 166 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Freeing thread data...\n",154 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Freeing ...\n", 167 155 pThread->uPID); 168 156 169 int rc = vboxServiceControlThreadRequestCancel(pThread->pRequest); 170 if (RT_FAILURE(rc)) 171 VBoxServiceError("ControlThread: [PID %u]: Signalling request event failed, rc=%Rrc\n", 172 pThread->uPID, rc); 173 174 rc = RTCritSectEnter(&pThread->CritSect); 157 int rc = RTCritSectEnter(&pThread->CritSect); 175 158 if (RT_SUCCESS(rc)) 176 159 { … … 189 172 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Setting stopped state\n", 190 173 pThread->uPID); 191 192 /* Set stopped status. */193 ASMAtomicXchgBool(&pThread->fStopped, true);194 174 195 175 rc = RTCritSectLeave(&pThread->CritSect); … … 220 200 * @param pThread Thread to shut down. 221 201 */ 222 int VBoxServiceControlThreadS ignalShutdown(const PVBOXSERVICECTRLTHREAD pThread)202 int VBoxServiceControlThreadStop(const PVBOXSERVICECTRLTHREAD pThread) 223 203 { 224 204 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 225 205 226 VBoxServiceVerbose(3, "ControlThread: [PID %u]: S ignalling shutdown...\n",206 VBoxServiceVerbose(3, "ControlThread: [PID %u]: Stopping ...\n", 227 207 pThread->uPID); 208 209 int rc = vboxServiceControlThreadRequestCancel(pThread->pRequest); 210 if (RT_FAILURE(rc)) 211 VBoxServiceError("ControlThread: [PID %u]: Signalling request event failed, rc=%Rrc\n", 212 pThread->uPID, rc); 228 213 229 214 /* Do *not* set pThread->fShutdown or other stuff here! … … 231 216 232 217 PVBOXSERVICECTRLREQUEST pRequest; 233 intrc = VBoxServiceControlThreadRequestAlloc(&pRequest, VBOXSERVICECTRLREQUEST_QUIT);218 rc = VBoxServiceControlThreadRequestAlloc(&pRequest, VBOXSERVICECTRLREQUEST_QUIT); 234 219 if (RT_SUCCESS(rc)) 235 220 { … … 252 237 * @param RTMSINTERVAL Timeout in ms to wait for shutdown. 253 238 */ 254 int VBoxServiceControlThreadWait ForShutdown(const PVBOXSERVICECTRLTHREAD pThread,255 239 int VBoxServiceControlThreadWait(const PVBOXSERVICECTRLTHREAD pThread, 240 RTMSINTERVAL msTimeout) 256 241 { 257 242 AssertPtrReturn(pThread, VERR_INVALID_POINTER); 258 243 int rc = VINF_SUCCESS; 259 244 if ( pThread->Thread != NIL_RTTHREAD 260 && !ASMAtomicReadBool(&pThread->fStopped)) /* Only shutdown threads which aren't yet. */245 && ASMAtomicReadBool(&pThread->fStarted)) 261 246 { 262 247 VBoxServiceVerbose(2, "ControlThread: [PID %u]: Waiting for shutdown ...\n", … … 286 271 287 272 /** 288 * Returns whether a guest process thread still is up and running.289 *290 * @return true if thread is running, false if not.291 * @param pThread Thread to determine current status for.292 */293 bool VBoxServiceControlThreadActive(const PVBOXSERVICECTRLTHREAD pThread)294 {295 AssertPtrReturn(pThread, false);296 297 int rc = RTCritSectEnter(&pThread->CritSect);298 if (RT_SUCCESS(rc))299 {300 /* We only are interested whether the thread really is alive301 * and kicking or not, meaning:302 * - thread was started303 * - thread is able to serve IPC messages304 *305 * Even if the fShutdown flag is set this means the thread should be306 * considered as being running (destruction phase).307 */308 bool fRunning = !pThread->fStopped;309 310 rc = RTCritSectLeave(&pThread->CritSect);311 AssertRC(rc);312 313 return fRunning;314 }315 316 return false;317 }318 319 320 /**321 273 * Closes the stdin pipe of a guest process. 322 274 * … … 509 461 case VBOXSERVICECTRLREQUEST_STDIN_WRITE_EOF: 510 462 { 511 AssertPtrReturn(pRequest->pvData, VERR_INVALID_POINTER);512 AssertReturn(pRequest->cbData, VERR_INVALID_PARAMETER);513 514 463 size_t cbWritten = 0; 515 if ( *phStdInW != NIL_RTPIPE 516 && pRequest->cbData) 464 if (pRequest->cbData) 517 465 { 518 rcReq = RTPipeWrite(*phStdInW, 519 pRequest->pvData, pRequest->cbData, &cbWritten); 466 AssertPtrReturn(pRequest->pvData, VERR_INVALID_POINTER); 467 if (*phStdInW != NIL_RTPIPE) 468 { 469 rcReq = RTPipeWrite(*phStdInW, 470 pRequest->pvData, pRequest->cbData, &cbWritten); 471 } 472 else 473 rcReq = VINF_EOF; 520 474 } 521 else522 rcReq = VINF_EOF;523 475 524 476 /* … … 1018 970 return VINF_SUCCESS; 1019 971 1020 VBoxServiceVerbose(4, "ControlThread: Cancelling request 972 VBoxServiceVerbose(4, "ControlThread: Cancelling request=0x%p\n", pReq); 1021 973 1022 974 return RTSemEventMultiSignal(pReq->Event); … … 1034 986 AssertPtrReturnVoid(pReq); 1035 987 1036 VBoxServiceVerbose(4, "ControlThread: Freeing request 0x%p (event 0x%p)\n",988 VBoxServiceVerbose(4, "ControlThread: Freeing request=0x%p (event=%RTsem)\n", 1037 989 pReq, &pReq->Event); 1038 990 … … 1401 1353 VBoxServiceVerbose(3, "ControlThread: Thread of process \"%s\" started\n", pThread->pszCmd); 1402 1354 1403 int rc = VbglR3GuestCtrlConnect(&pThread->uClientID); 1355 int rc = VBoxServiceControlListSet(VBOXSERVICECTRLTHREADLIST_RUNNING, pThread); 1356 AssertRC(rc); 1357 1358 rc = VbglR3GuestCtrlConnect(&pThread->uClientID); 1404 1359 if (RT_FAILURE(rc)) 1405 1360 { … … 1521 1476 hProcess, pThread->uTimeLimitMS, hPollSet, 1522 1477 &pThread->pipeStdInW, &pipeStdOutR, &pipeStdErrR); 1478 1523 1479 /* 1524 1480 * The handles that are no longer in the set have … … 1567 1523 } 1568 1524 1525 /* Move thread to stopped thread list. */ 1526 int rc2 = VBoxServiceControlListSet(VBOXSERVICECTRLTHREADLIST_STOPPED, pThread); 1527 AssertRC(rc2); 1528 1569 1529 if (pThread->uClientID) 1570 1530 { 1571 int rc2;1572 1531 if (RT_FAILURE(rc)) 1573 1532 { … … 1601 1560 pThread->uPID, pThread->pszCmd, rc); 1602 1561 1562 /* Update started/stopped status. */ 1563 ASMAtomicXchgBool(&pThread->fStopped, true); 1603 1564 ASMAtomicXchgBool(&pThread->fStarted, false); 1604 1565 … … 1610 1571 RTThreadUserSignal(RTThreadSelf()); 1611 1572 1612 /*1613 * Remove thread from global thread list. After this it's safe to shutdown1614 * and deallocate this thread.1615 */1616 VBoxServiceControlRemoveThread(pThread);1617 1618 int rc2 = vboxServiceControlThreadFree(pThread);1619 if (RT_SUCCESS(rc))1620 rc = rc2;1621 1622 1573 return rc; 1623 1574 } … … 1645 1596 * 1646 1597 * @return IPRT status code. 1647 * @param uClientID Client ID for accessing host service.1648 1598 * @param uContextID Context ID to associate the process to start with. 1649 * @param pszCmd Full qualified path of process to start (without arguments). 1650 * @param uFlags Process execution flags. 1651 * @param pszArgs String of arguments to pass to the process to start. 1652 * @param uNumArgs Number of arguments specified in pszArgs. 1653 * @param pszEnv String of environment variables ("FOO=BAR") to pass to the process 1654 * to start. 1655 * @param cbEnv Size (in bytes) of environment variables. 1656 * @param uNumEnvVars Number of environment variables specified in pszEnv. 1657 * @param pszUser User name (account) to start the process under. 1658 * @param pszPassword Password of specified user name (account). 1659 * @param uTimeLimitMS Time limit (in ms) of the process' life time. 1660 * @param ppNode The thread's list node to insert into the global thread list 1661 * on success. 1662 * 1663 ** @todo Put (all?) these parameters into a struct! 1664 */ 1665 int VBoxServiceControlThreadStart(uint32_t uClientID, uint32_t uContextID, 1666 const char *pszCmd, uint32_t uFlags, 1667 const char *pszArgs, uint32_t uNumArgs, 1668 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars, 1669 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS, 1670 PRTLISTNODE *ppNode) 1671 { 1672 AssertPtrReturn(ppNode, VERR_INVALID_POINTER); 1599 * @param pProcess Process info. 1600 */ 1601 int VBoxServiceControlThreadStart(uint32_t uContextID, 1602 PVBOXSERVICECTRLPROCESS pProcess) 1603 { 1604 AssertPtrReturn(pProcess, VERR_INVALID_POINTER); 1673 1605 1674 1606 /* … … 1679 1611 return VERR_NO_MEMORY; 1680 1612 1681 int rc = gstsvcCntlExecThreadInit(pThread, 1682 uContextID, 1683 pszCmd, uFlags, 1684 pszArgs, uNumArgs, 1685 pszEnv, cbEnv, uNumEnvVars, 1686 pszUser, pszPassword, 1687 uTimeLimitMS); 1613 int rc = gstsvcCntlExecThreadInit(pThread, pProcess, uContextID); 1688 1614 if (RT_SUCCESS(rc)) 1689 1615 { … … 1693 1619 rc = RTThreadCreateF(&pThread->Thread, VBoxServiceControlThread, 1694 1620 pThread /*pvUser*/, 0 /*cbStack*/, 1695 RTTHREADTYPE_DEFAULT, 0 /* Flags */, "gctl%u", s_uCtrlExecThread);1621 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "gctl%u", s_uCtrlExecThread); 1696 1622 if (RT_FAILURE(rc)) 1697 1623 { … … 1704 1630 1705 1631 /* Wait for the thread to initialize. */ 1706 RTThreadUserWait(pThread->Thread, 60 * 1000 /* 60 seconds max. */); 1707 if (ASMAtomicReadBool(&pThread->fShutdown)) 1632 rc = RTThreadUserWait(pThread->Thread, 60 * 1000 /* 60 seconds max. */); 1633 AssertRC(rc); 1634 if ( ASMAtomicReadBool(&pThread->fShutdown) 1635 || RT_FAILURE(rc)) 1708 1636 { 1709 VBoxServiceError("ControlThread: Thread for process \"%s\" failed to start !\n", pszCmd);1710 rc = VERR_GENERAL_FAILURE;1637 VBoxServiceError("ControlThread: Thread for process \"%s\" failed to start, rc=%Rrc\n", 1638 pProcess->szCmd, rc); 1711 1639 } 1712 1640 else 1713 1641 { 1714 pThread->fStarted = true; 1715 1716 /* Return the thread's node. */ 1717 *ppNode = &pThread->Node; 1642 ASMAtomicXchgBool(&pThread->fStarted, true); 1718 1643 } 1719 1644 } … … 1742 1667 1743 1668 int rc = VINF_SUCCESS; 1744 PVBOXSERVICECTRLTHREAD pThread = VBoxServiceControl GetThreadLocked(uPID);1669 PVBOXSERVICECTRLTHREAD pThread = VBoxServiceControlLockThread(uPID); 1745 1670 if (pThread) 1746 1671 { … … 1773 1698 } 1774 1699 1775 VBoxServiceControl ThreadUnlock(pThread);1700 VBoxServiceControlUnlockThread(pThread); 1776 1701 } 1777 1702 else /* PID not found! */ -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h
r39843 r39906 29 29 30 30 #include <VBox/VBoxGuestLib.h> 31 #include <VBox/HostServices/GuestControlSvc.h> 31 32 32 33 /** … … 156 157 157 158 /** 159 * Thread list types. 160 */ 161 typedef enum VBOXSERVICECTRLTHREADLISTTYPE 162 { 163 /** Unknown list -- uncool to use. */ 164 VBOXSERVICECTRLTHREADLIST_UNKNOWN = 0, 165 /** Stopped list: Here all guest threads end up 166 * when they reached the stopped state and can 167 * be shut down / free'd safely. */ 168 VBOXSERVICECTRLTHREADLIST_STOPPED = 1, 169 /** 170 * Started list: Here all threads are registered 171 * when they're up and running (that is, accepting 172 * commands). 173 */ 174 VBOXSERVICECTRLTHREADLIST_RUNNING = 2 175 } VBOXSERVICECTRLTHREADLISTTYPE; 176 177 /** 158 178 * Structure to perform a request on a started guest 159 179 * process. Needed for letting the main guest control thread … … 183 203 184 204 /** 205 * Structure holding information for starting a guest 206 * process. 207 */ 208 typedef struct VBOXSERVICECTRLPROCESS 209 { 210 /** Full qualified path of process to start (without arguments). */ 211 char szCmd[GUESTPROCESS_MAX_CMD_LEN]; 212 /** Process execution flags. @sa */ 213 uint32_t uFlags; 214 /** Command line arguments. */ 215 char szArgs[GUESTPROCESS_MAX_ARGS_LEN]; 216 /** Number of arguments specified in pszArgs. */ 217 uint32_t uNumArgs; 218 /** String of environment variables ("FOO=BAR") to pass to the process 219 * to start. */ 220 char szEnv[GUESTPROCESS_MAX_ENV_LEN]; 221 /** Size (in bytes) of environment variables block. */ 222 uint32_t cbEnv; 223 /** Number of environment variables specified in pszEnv. */ 224 uint32_t uNumEnvVars; 225 /** User name (account) to start the process under. */ 226 char szUser[GUESTPROCESS_MAX_USER_LEN]; 227 /** Password of specified user name (account). */ 228 char szPassword[GUESTPROCESS_MAX_PASSWORD_LEN]; 229 /** Time limit (in ms) of the process' life time. */ 230 uint32_t uTimeLimitMS; 231 } VBOXSERVICECTRLPROCESS; 232 /** Pointer to a guest process block. */ 233 typedef VBOXSERVICECTRLPROCESS *PVBOXSERVICECTRLPROCESS; 234 235 /** 185 236 * Structure for holding data for one (started) guest process. 186 237 */ 187 238 typedef struct VBOXSERVICECTRLTHREAD 188 239 { 240 /** Pointer to list archor of following 241 * list node. 242 * @todo Would be nice to have a RTListGetAnchor(). */ 243 PRTLISTANCHOR pAnchor; 189 244 /** Node. */ 190 245 RTLISTNODE Node; … … 330 385 331 386 #ifdef VBOX_WITH_GUEST_CONTROL 332 /* Guest control functions. */ 333 extern PVBOXSERVICECTRLTHREAD VBoxServiceControlGetThreadLocked(uint32_t uPID); 334 extern void VBoxServiceControlThreadUnlock(const PVBOXSERVICECTRLTHREAD pThread); 335 extern int VBoxServiceControlAssignPID(PVBOXSERVICECTRLTHREAD pThread, uint32_t uPID); 336 extern void VBoxServiceControlRemoveThread(const PVBOXSERVICECTRLTHREAD pThread); 337 /* Guest process functions. */ 338 extern bool VBoxServiceControlThreadActive(const PVBOXSERVICECTRLTHREAD pThread); 339 extern int VBoxServiceControlThreadStart(uint32_t uClientID, uint32_t uContext, 340 const char *pszCmd, uint32_t uFlags, 341 const char *pszArgs, uint32_t uNumArgs, 342 const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars, 343 const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS, 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); 353 extern int VBoxServiceControlThreadPerform(uint32_t uPID, PVBOXSERVICECTRLREQUEST pRequest); 354 extern int VBoxServiceControlThreadSignalShutdown(const PVBOXSERVICECTRLTHREAD pThread); 355 extern int VBoxServiceControlThreadWaitForShutdown(const PVBOXSERVICECTRLTHREAD pThread, RTMSINTERVAL msTimeout); 387 /* Guest control main thread functions. */ 388 extern int VBoxServiceControlAssignPID(PVBOXSERVICECTRLTHREAD pThread, uint32_t uPID); 389 extern int VBoxServiceControlListSet(VBOXSERVICECTRLTHREADLISTTYPE enmList, 390 PVBOXSERVICECTRLTHREAD pThread); 391 extern PVBOXSERVICECTRLTHREAD VBoxServiceControlLockThread(uint32_t uPID); 392 extern void VBoxServiceControlUnlockThread(const PVBOXSERVICECTRLTHREAD pThread); 393 extern int VBoxServiceControlSetInactive(PVBOXSERVICECTRLTHREAD pThread); 394 /* Per-thread guest process functions. */ 395 extern int VBoxServiceControlThreadStart(uint32_t uContext, 396 PVBOXSERVICECTRLPROCESS pProcess); 397 extern int VBoxServiceControlThreadPerform(uint32_t uPID, PVBOXSERVICECTRLREQUEST pRequest); 398 extern int VBoxServiceControlThreadStop(const PVBOXSERVICECTRLTHREAD pThread); 399 extern int VBoxServiceControlThreadWait(const PVBOXSERVICECTRLTHREAD pThread, RTMSINTERVAL msTimeout); 400 extern int VBoxServiceControlThreadFree(PVBOXSERVICECTRLTHREAD pThread); 401 /* Request handling. */ 402 extern int VBoxServiceControlThreadRequestAlloc(PVBOXSERVICECTRLREQUEST *ppReq, 403 VBOXSERVICECTRLREQUESTTYPE enmType); 404 extern int VBoxServiceControlThreadRequestAllocEx(PVBOXSERVICECTRLREQUEST *ppReq, 405 VBOXSERVICECTRLREQUESTTYPE enmType, 406 void* pbData, 407 size_t cbData, 408 uint32_t uCID); 409 extern void VBoxServiceControlThreadRequestFree(PVBOXSERVICECTRLREQUEST pReq); 356 410 #endif /* VBOX_WITH_GUEST_CONTROL */ 357 411
Note:
See TracChangeset
for help on using the changeset viewer.