Changeset 44935 in vbox for trunk/src/VBox/Additions/common
- Timestamp:
- Mar 6, 2013 4:40:36 PM (12 years ago)
- Location:
- trunk/src/VBox/Additions/common/VBoxService
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.cpp
r44869 r44935 193 193 if (RT_SUCCESS(rc)) 194 194 { 195 VBoxServiceVerbose(3, "Service client ID: %#x\n", g_uControlSvcClientID); 195 VBoxServiceVerbose(3, "Guest control service client ID=%RU32\n", 196 g_uControlSvcClientID); 196 197 197 198 /* Init lists. */ … … 836 837 * wants to use. Store it in the host context for later calls. */ 837 838 pHostCtx->uProtocol = ssInfo.uProtocol; 839 VBoxServiceVerbose(3, "Client ID=%RU32 now is using protocol %RU32\n", 840 pHostCtx->uClientID, pHostCtx->uProtocol); 838 841 839 842 rc = GstCntlSessionOpen(&ssInfo, NULL /* Node */); -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h
r44869 r44935 255 255 /** Domain of the user account. */ 256 256 char szDomain[GUESTPROCESS_MAX_DOMAIN_LEN]; 257 /** Session creation flags. */ 257 /** Session creation flags. 258 * @sa VBOXSERVICECTRLSESSIONSTARTUPFLAG_* flags. */ 258 259 uint32_t uFlags; 259 260 } VBOXSERVICECTRLSESSIONSTARTUPINFO; … … 262 263 263 264 /** 264 * Structure for one (opened) guest session.265 * Structure for a (forked) guest session. 265 266 */ 266 267 typedef struct VBOXSERVICECTRLSESSION … … 278 279 /** Process handle for forked child. */ 279 280 RTPROCESS hProcess; 281 /** Shutdown indicator; will be set when the thread 282 * needs (or is asked) to shutdown. */ 283 bool volatile fShutdown; 284 /** Indicator set by the service thread exiting. */ 285 bool volatile fStopped; 286 /** Whether the thread was started or not. */ 287 bool fStarted; 288 #if 0 /* Pipe IPC not used yet. */ 280 289 /** Pollset containing all the pipes. */ 281 290 RTPOLLSET hPollSet; … … 295 304 /** The other end of hNotificationPipeW. */ 296 305 RTPIPE hNotificationPipeR; 306 #endif 297 307 } VBOXSERVICECTRLSESSION; 298 308 /** Pointer to thread data. */ … … 314 324 extern int GstCntlSessionOpen(const PVBOXSERVICECTRLSESSIONSTARTUPINFO pSessionStartupInfo, PRTLISTNODE pNode); 315 325 extern int GstCntlSessionClose(PVBOXSERVICECTRLSESSION pSession, uint32_t uFlags); 326 extern int GstCntlSessionTerminate(PVBOXSERVICECTRLSESSION pSession); 316 327 extern RTEXITCODE VBoxServiceControlSessionForkInit(int argc, char **argv); 317 328 -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp
r44926 r44935 21 21 * Header Files * 22 22 *******************************************************************************/ 23 #include <iprt/asm.h> 23 24 #include <iprt/assert.h> 24 25 #include <iprt/env.h> … … 56 57 static int gstcntlSessionHandleFileSeek(uint32_t uClientId, uint32_t cParms); 57 58 static int gstcntlSessionHandleFileTell(uint32_t uClientId, uint32_t cParms); 59 static DECLCALLBACK(int) gstcntlSessionThread(RTTHREAD ThreadSelf, void *pvUser); 58 60 59 61 /** The session ID of the forked session process. */ … … 475 477 476 478 479 /** 480 * Thread main routine for a forked guest session. This 481 * thread runs in the main executable to control the forked 482 * session process. 483 * 484 * @return IPRT status code. 485 * @param RTTHREAD Pointer to the thread's data. 486 * @param void* User-supplied argument pointer. 487 * 488 */ 489 static DECLCALLBACK(int) gstcntlSessionThread(RTTHREAD ThreadSelf, void *pvUser) 490 { 491 PVBOXSERVICECTRLSESSION pSession = (PVBOXSERVICECTRLSESSION)pvUser; 492 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 493 494 VBoxServiceVerbose(3, "Session ID=%RU32 thread running\n", 495 pSession->StartupInfo.uSessionID); 496 497 int rc = VINF_SUCCESS; 498 499 /* Let caller know that we're done initializing. */ 500 int rc2 = RTThreadUserSignal(RTThreadSelf()); 501 if (RT_SUCCESS(rc)) 502 rc = rc2; 503 504 if (RT_SUCCESS(rc)) 505 { 506 RTPROCSTATUS ProcessStatus; 507 int rc2; 508 for (;;) 509 { 510 rc2 = RTProcWaitNoResume(pSession->hProcess, RTPROCWAIT_FLAGS_BLOCK, 511 &ProcessStatus); 512 if (RT_UNLIKELY(rc2 == VERR_INTERRUPTED)) 513 continue; 514 else if ( rc2 == VINF_SUCCESS 515 || rc2 == VERR_PROCESS_NOT_FOUND) 516 { 517 break; 518 } 519 else 520 AssertMsgBreak(rc2 == VERR_PROCESS_RUNNING, 521 ("Got unexpected rc=%Rrc while waiting for session process termination\n", rc2)); 522 } 523 524 VBoxServiceVerbose(3, "Guest session process ID=%RU32 terminated with rc=%Rrc, reason=%ld, status=%d\n", 525 pSession->StartupInfo.uSessionID, rc, 526 ProcessStatus.enmReason, ProcessStatus.iStatus); 527 } 528 529 VBoxServiceVerbose(3, "Session ID=%RU32 thread ended\n", pSession->StartupInfo.uSessionID); 530 return rc; 531 } 532 533 477 534 RTEXITCODE gstcntlSessionWorker(void) 478 535 { 479 536 bool fSessionFilter = true; 537 538 VBoxServiceVerbose(0, "Hi, this is guest session ID=%RU32\n", 539 g_uSessionID); 480 540 481 541 uint32_t uClientID; … … 487 547 488 548 rc = VbglR3GuestCtrlMsgSetFilter(uClientID, uFilterAdd, 0 /* Filter remove */); 549 VBoxServiceVerbose(3, "Setting message filterAdd=%RU32 returned %Rrc\n", 550 uFilterAdd, rc); 551 489 552 if ( RT_FAILURE(rc) 490 553 && rc == VERR_NOT_SUPPORTED) … … 531 594 { 532 595 VBoxServiceVerbose(3, "Msg=%RU32 (%RU32 parms) retrieved\n", uMsg, cParms); 533 } 534 535 VBoxServiceVerbose(3, "Msg=%RU32 (%RU32 parms) retrieved\n", uMsg, cParms); 536 537 /** @todo Guest session ID change detection? */ 538 539 switch (uMsg) 540 { 541 case HOST_CANCEL_PENDING_WAITS: 542 /* Fall thru is intentional. */ 543 case HOST_SESSION_CLOSE: 544 /* Shutdown this fork. */ 545 rc = gstcntlSessionForkShutdown(uClientID, cParms); 546 fShutdown = true; /* Shutdown in any case. */ 547 break; 548 549 case HOST_FILE_OPEN: 550 rc = gstcntlSessionHandleFileOpen(uClientID, cParms); 551 break; 552 553 case HOST_FILE_CLOSE: 554 rc = gstcntlSessionHandleFileClose(uClientID, cParms); 555 break; 556 557 case HOST_FILE_READ: 558 rc = gstcntlSessionHandleFileRead(uClientID, cParms, 559 pvScratchBuf, cbScratchBuf); 560 break; 561 562 case HOST_FILE_READ_AT: 563 rc = gstcntlSessionHandleFileReadAt(uClientID, cParms, 564 pvScratchBuf, cbScratchBuf); 565 break; 566 567 case HOST_FILE_WRITE: 568 rc = gstcntlSessionHandleFileWrite(uClientID, cParms, 569 pvScratchBuf, cbScratchBuf); 570 break; 571 572 case HOST_FILE_WRITE_AT: 573 rc = gstcntlSessionHandleFileWriteAt(uClientID, cParms, 574 pvScratchBuf, cbScratchBuf); 575 break; 576 577 case HOST_FILE_SEEK: 578 rc = gstcntlSessionHandleFileSeek(uClientID, cParms); 579 break; 580 581 case HOST_FILE_TELL: 582 rc = gstcntlSessionHandleFileTell(uClientID, cParms); 583 break; 584 585 default: 586 VBoxServiceVerbose(3, "Unsupported message from host, uMsg=%RU32, cParms=%RU32\n", 587 uMsg, cParms); 588 /* Don't terminate here; just wait for the next message. */ 589 break; 596 597 /** @todo Guest session ID change detection? */ 598 599 switch (uMsg) 600 { 601 case HOST_CANCEL_PENDING_WAITS: 602 /* Fall thru is intentional. */ 603 case HOST_SESSION_CLOSE: 604 /* Shutdown this fork. */ 605 rc = gstcntlSessionForkShutdown(uClientID, cParms); 606 fShutdown = true; /* Shutdown in any case. */ 607 break; 608 609 case HOST_FILE_OPEN: 610 rc = gstcntlSessionHandleFileOpen(uClientID, cParms); 611 break; 612 613 case HOST_FILE_CLOSE: 614 rc = gstcntlSessionHandleFileClose(uClientID, cParms); 615 break; 616 617 case HOST_FILE_READ: 618 rc = gstcntlSessionHandleFileRead(uClientID, cParms, 619 pvScratchBuf, cbScratchBuf); 620 break; 621 622 case HOST_FILE_READ_AT: 623 rc = gstcntlSessionHandleFileReadAt(uClientID, cParms, 624 pvScratchBuf, cbScratchBuf); 625 break; 626 627 case HOST_FILE_WRITE: 628 rc = gstcntlSessionHandleFileWrite(uClientID, cParms, 629 pvScratchBuf, cbScratchBuf); 630 break; 631 632 case HOST_FILE_WRITE_AT: 633 rc = gstcntlSessionHandleFileWriteAt(uClientID, cParms, 634 pvScratchBuf, cbScratchBuf); 635 break; 636 637 case HOST_FILE_SEEK: 638 rc = gstcntlSessionHandleFileSeek(uClientID, cParms); 639 break; 640 641 case HOST_FILE_TELL: 642 rc = gstcntlSessionHandleFileTell(uClientID, cParms); 643 break; 644 645 default: 646 VBoxServiceVerbose(3, "Unsupported message from host, uMsg=%RU32, cParms=%RU32\n", 647 uMsg, cParms); 648 /* Don't terminate here; just wait for the next message. */ 649 break; 650 } 590 651 } 591 652 592 653 if (fShutdown) 593 654 break; 655 656 /* Let's sleep for a bit and let others run ... */ 657 RTThreadYield(); 594 658 } 595 659 } … … 610 674 /** 611 675 * Creates a guest session. This will spawn a new VBoxService.exe instance under 612 * behalf of the given user which then will act as a session host. 676 * behalf of the given user which then will act as a session host. On successful 677 * open, the session will be added to the session list. 613 678 * 614 679 * @return IPRT status code. … … 645 710 memcpy(&pSession->StartupInfo, pSessionStartupInfo, sizeof(VBOXSERVICECTRLSESSIONSTARTUPINFO)); 646 711 647 VBoxServiceVerbose(3, "Forking new guest session szUser=%s, szPassword=%s, szDomain=%s, uFlags=%x, using protocol %RU32\n", 648 pSessionStartupInfo->szUser, 712 pSession->fShutdown = false; 713 pSession->fStarted = false; 714 pSession->fStopped = false; 715 716 /* Is this an anonymous session? */ 717 /* Anonymous sessions run with the same privileges as the main VBoxService executable. */ 718 bool fAnonymous = !RT_BOOL(strlen(pSession->StartupInfo.szUser)); 719 if (fAnonymous) 720 { 721 Assert(!strlen(pSession->StartupInfo.szPassword)); 722 Assert(!strlen(pSession->StartupInfo.szDomain)); 723 724 VBoxServiceVerbose(3, "New anonymous guest session ID=%RU32 created, uFlags=%x, using protocol %RU32\n", 725 pSessionStartupInfo->uSessionID, 726 pSessionStartupInfo->uFlags, 727 pSessionStartupInfo->uProtocol); 728 } 729 else 730 { 731 VBoxServiceVerbose(3, "Forking new guest session ID=%RU32, szUser=%s, szPassword=%s, szDomain=%s, uFlags=%x, using protocol %RU32\n", 732 pSessionStartupInfo->uSessionID, 733 pSessionStartupInfo->szUser, 649 734 #ifdef DEBUG 650 pSessionStartupInfo->szPassword,735 pSessionStartupInfo->szPassword, 651 736 #else 652 "XXX", /* Never show passwords in release mode. */737 "XXX", /* Never show passwords in release mode. */ 653 738 #endif 654 pSessionStartupInfo->szDomain, 655 pSessionStartupInfo->uFlags, 656 pSessionStartupInfo->uProtocol); 739 pSessionStartupInfo->szDomain, 740 pSessionStartupInfo->uFlags, 741 pSessionStartupInfo->uProtocol); 742 } 657 743 658 744 rc = RTCritSectInit(&pSession->CritSect); … … 665 751 { 666 752 char szParmUserName[GUESTPROCESS_MAX_USER_LEN + 32]; 667 if (!RTStrPrintf(szParmUserName, sizeof(szParmUserName), "--username=%s", pSession->StartupInfo.szUser)) 668 rc = VERR_BUFFER_OVERFLOW; 753 if (!fAnonymous) 754 { 755 if (!RTStrPrintf(szParmUserName, sizeof(szParmUserName), "--username=%s", pSession->StartupInfo.szUser)) 756 rc = VERR_BUFFER_OVERFLOW; 757 } 669 758 char szParmSessionID[32]; 670 759 if (RT_SUCCESS(rc) && !RTStrPrintf(szParmSessionID, sizeof(szParmSessionID), "--session-id=%RU32", … … 689 778 papszArgs[iOptIdx++] = szParmSessionID; 690 779 papszArgs[iOptIdx++] = szParmSessionProto; 691 papszArgs[iOptIdx++] = szParmUserName; 780 if (!fAnonymous) 781 papszArgs[iOptIdx++] = szParmUserName; 692 782 693 783 /* Add same verbose flags as parent process. */ … … 733 823 { 734 824 if (!RTStrPrintf(szParmLogFile, sizeof(szParmLogFile), 735 "--logfile 825 "--logfile=%s", pszLogFile)) 736 826 { 737 827 rc2 = VERR_BUFFER_OVERFLOW; … … 798 888 rc = RTProcCreateEx(pszExeName, papszArgs, RTENV_DEFAULT, uProcFlags, 799 889 pSession->StdIn.phChild, pSession->StdOut.phChild, pSession->StdErr.phChild, 800 pSession->StartupInfo.szUser,801 pSession->StartupInfo.szPassword,890 !fAnonymous ? pSession->StartupInfo.szUser : NULL, 891 !fAnonymous ? pSession->StartupInfo.szPassword : NULL, 802 892 &pSession->hProcess); 803 893 } … … 818 908 } 819 909 #else 820 /** @todo Do we need a custom environment block? */ 821 rc = RTProcCreateEx(pszExeName, papszArgs, RTENV_DEFAULT, uProcFlags, 822 NULL /* StdIn */, NULL /* StdOut */, NULL /* StdErr */, 823 pSession->StartupInfo.szUser, 824 pSession->StartupInfo.szPassword, 825 &pSession->hProcess); 910 RTHANDLE hStdIn; 911 rc = RTFileOpenBitBucket(&hStdIn.u.hFile, RTFILE_O_READ); 912 if (RT_SUCCESS(rc)) 913 { 914 hStdIn.enmType = RTHANDLETYPE_FILE; 915 916 RTHANDLE hStdOutAndErr; 917 rc = RTFileOpenBitBucket(&hStdOutAndErr.u.hFile, RTFILE_O_WRITE); 918 if (RT_SUCCESS(rc)) 919 { 920 hStdOutAndErr.enmType = RTHANDLETYPE_FILE; 921 922 /** @todo Do we need a custom/cloned environment block? */ 923 rc = RTProcCreateEx(pszExeName, papszArgs, RTENV_DEFAULT, uProcFlags, 924 &hStdIn, &hStdOutAndErr, &hStdOutAndErr, 925 !fAnonymous ? pSession->StartupInfo.szUser : NULL, 926 !fAnonymous ? pSession->StartupInfo.szPassword : NULL, 927 &pSession->hProcess); 928 929 RTFileClose(hStdOutAndErr.u.hFile); 930 } 931 932 RTFileClose(hStdOutAndErr.u.hFile); 933 } 826 934 #endif 827 935 } … … 832 940 if (RT_SUCCESS(rc)) 833 941 { 834 /* Add session to list. */ 835 /* rc = */ RTListAppend(&g_lstControlSessions, &pSession->Node); 836 if (pNode) /* Return node if wanted. */ 837 pNode = &pSession->Node; 838 } 839 else 942 /* Start session thread. */ 943 static uint32_t s_uCtrlSessionThread = 0; 944 if (s_uCtrlSessionThread++ == UINT32_MAX) 945 s_uCtrlSessionThread = 0; /* Wrap around to not let IPRT freak out. */ 946 rc = RTThreadCreateF(&pSession->Thread, gstcntlSessionThread, 947 pSession /*pvUser*/, 0 /*cbStack*/, 948 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "sess%u", s_uCtrlSessionThread); 949 if (RT_FAILURE(rc)) 950 { 951 VBoxServiceError("Creating session thread failed, rc=%Rrc\n", rc); 952 } 953 else 954 { 955 /* Wait for the thread to initialize. */ 956 rc = RTThreadUserWait(pSession->Thread, 60 * 1000 /* 60 seconds max. */); 957 AssertRC(rc); 958 if ( ASMAtomicReadBool(&pSession->fShutdown) 959 || RT_FAILURE(rc)) 960 { 961 VBoxServiceError("Thread for session ID=%RU32 failed to start\n", 962 pSession->StartupInfo.uSessionID); 963 rc = VERR_CANT_CREATE; /** @todo Find a better rc. */ 964 } 965 else 966 { 967 ASMAtomicXchgBool(&pSession->fStarted, true); 968 969 /* Add session to list. */ 970 /* rc = */ RTListAppend(&g_lstControlSessions, &pSession->Node); 971 if (pNode) /* Return node if wanted. */ 972 pNode = &pSession->Node; 973 } 974 } 975 } 976 977 if (RT_FAILURE(rc)) 840 978 { 841 979 RTMemFree(pSession); … … 851 989 852 990 /** 853 * Closes a formerly opened guest session. 991 * Closes a formerly opened guest session and removes it from 992 * the session list. 854 993 * 855 994 * @return IPRT status code. 856 995 * @param pSession Guest session to close. 857 * @param uFlags Terminationflags.996 * @param uFlags Closing flags. 858 997 */ 859 998 int GstCntlSessionClose(PVBOXSERVICECTRLSESSION pSession, uint32_t uFlags) … … 861 1000 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 862 1001 863 /** @todo Implement session termination. */ 864 return VERR_NOT_IMPLEMENTED; 1002 int rc = VINF_SUCCESS; 1003 1004 /* The fork should have received the same closing request, 1005 * so just wait 30s for the process to close. On timeout kill 1006 * it in a not so gentle manner. */ 1007 if ( pSession->Thread != NIL_RTTHREAD 1008 && ASMAtomicReadBool(&pSession->fStarted)) 1009 { 1010 bool fAlive = true; 1011 uint64_t u64Start = RTTimeMilliTS(); 1012 uint32_t cMsTimeout = 30 * 1000; /* 30 seconds. */ 1013 1014 VBoxServiceVerbose(3, "Waiting for session ID=%RU32 to close (%RU32ms) ...\n", 1015 pSession->StartupInfo.uSessionID, cMsTimeout); 1016 1017 int rcThread; 1018 rc = RTThreadWait(pSession->Thread, cMsTimeout, &rcThread); 1019 if (RT_FAILURE(rc)) 1020 { 1021 VBoxServiceError("Waiting for session ID=%RU32 to close failed with rc=%Rrc\n", rc); 1022 } 1023 else 1024 { 1025 fAlive = false; 1026 VBoxServiceVerbose(3, "Session ID=%RU32 thread ended with rc=%Rrc\n", 1027 pSession->StartupInfo.uSessionID, rcThread); 1028 } 1029 #if 0 1030 for (;;) 1031 { 1032 uint64_t u64Now = RTTimeMilliTS(); 1033 uint64_t cMsElapsed = u64Now - u64Start; 1034 1035 if (cMsElapsed >= cMsTimeout) 1036 break; 1037 1038 RTPROCSTATUS ProcessStatus; 1039 int rc2 = RTProcWaitNoResume(pSession->hProcess, RTPROCWAIT_FLAGS_NOBLOCK, 1040 &ProcessStatus); 1041 if (RT_UNLIKELY(rc2 == VERR_INTERRUPTED)) 1042 continue; 1043 else if ( rc2 == VINF_SUCCESS 1044 || rc2 == VERR_PROCESS_NOT_FOUND) 1045 { 1046 fAlive = false; 1047 break; 1048 } 1049 else 1050 AssertMsgBreak(rc2 == VERR_PROCESS_RUNNING, 1051 ("Got unexpected rc=%Rrc while waiting for session process termination\n", rc2)); 1052 1053 RTThreadSleep(100); /* Wait a bit. */ 1054 } 1055 #endif 1056 1057 if (fAlive) 1058 { 1059 VBoxServiceVerbose(3, "Session ID=%RU32 still alive, killing ...\n", 1060 pSession->StartupInfo.uSessionID); 1061 int rc2 = GstCntlSessionTerminate(pSession); 1062 if (RT_SUCCESS(rc)) 1063 rc = rc2; 1064 } 1065 else 1066 VBoxServiceVerbose(3, "Session ID=%RU32 has been closed\n", 1067 pSession->StartupInfo.uSessionID); 1068 1069 /* Remove session from list and destroy object. */ 1070 RTListNodeRemove(&pSession->Node); 1071 1072 RTMemFree(pSession); 1073 pSession = NULL; 1074 } 1075 1076 return rc; 865 1077 } 866 1078 … … 870 1082 * 871 1083 * @return IPRT status code. 872 * @param uFlags Terminationflags.1084 * @param uFlags Closing flags. 873 1085 */ 874 1086 int GstCntlSessionCloseAll(uint32_t uFlags) … … 876 1088 int rc = VINF_SUCCESS; 877 1089 878 VBoxServiceVerbose(3, "GstCntlSessionCloseAll\n");879 880 1090 PVBOXSERVICECTRLSESSION pSessionCur; 881 1091 RTListForEach(&g_lstControlSessions, pSessionCur, VBOXSERVICECTRLSESSION, Node) … … 887 1097 /* Keep going. */ 888 1098 } 1099 } 1100 1101 return rc; 1102 } 1103 1104 1105 /** 1106 * Terminates a formerly opened guest session. Only 1107 * use this as a last action! 1108 * 1109 * @return IPRT status code. 1110 * @param pSession Guest session to terminate. 1111 */ 1112 int GstCntlSessionTerminate(PVBOXSERVICECTRLSESSION pSession) 1113 { 1114 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 1115 1116 int rc; 1117 1118 for (int i = 0; i < 3; i++) 1119 { 1120 rc = RTProcTerminate(pSession->hProcess); 1121 if (RT_SUCCESS(rc)) 1122 break; 1123 RTThreadSleep(1000); 889 1124 } 890 1125 … … 972 1207 static int gstcntlSessionForkShutdown(uint32_t uClientId, uint32_t cParms) 973 1208 { 974 VBoxServiceVerbose(0, "Session %RU32 is goingto shutdown ...\n", g_uSessionID);1209 VBoxServiceVerbose(0, "Session %RU32 is about to shutdown ...\n", g_uSessionID); 975 1210 976 1211 /* Close all left guest files. */
Note:
See TracChangeset
for help on using the changeset viewer.