Changeset 31019 in vbox
- Timestamp:
- Jul 22, 2010 5:48:18 PM (15 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 24 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp
r31016 r31019 824 824 825 825 // open a session 826 SessionType_T st; 827 CHECK_ERROR_BREAK(m, LockForSession(session, false /* fPermitShared */, &st)); 826 CHECK_ERROR_BREAK(m, LockMachine(session, LockType_Write)); 828 827 fSessionOpened = true; 829 828 -
trunk/src/VBox/Frontends/VBoxHeadless/testcase/tstHeadless.cpp
r31016 r31019 150 150 { 151 151 RTPrintf ("Opening an existing session...\n"); 152 SessionType_T st; 153 CHECK_ERROR_BREAK(m, LockForSession(session, true /* fPermitShared */, &st)); 152 CHECK_ERROR_BREAK(m, LockMachine(session, LockType_Shared)); 154 153 155 154 ComPtr <IConsole> console; -
trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
r31016 r31019 1864 1864 CHECK_ERROR_RET(aVirtualBox, FindMachine(Bstr(argv[0]), ptrMachine.asOutParam()), 1); 1865 1865 1866 SessionType_T st; 1867 CHECK_ERROR_RET(ptrMachine, LockForSession(aSession, true /* fPermitShared */, &st), 1); 1866 CHECK_ERROR_RET(ptrMachine, LockMachine(aSession, LockType_Shared), 1); 1868 1867 1869 1868 /* -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
r31016 r31019 88 88 89 89 /* open a session for the VM */ 90 SessionType_T st; 91 CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1); 90 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1); 92 91 93 92 do -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r31016 r31019 286 286 { 287 287 /* open an existing session for VM */ 288 SessionType_T st; 289 CHECK_ERROR_BREAK(machine, LockForSession(a->session, true /* fPermitShared */, &st)); 288 CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Shared)); 290 289 // @todo r=dj assert that it's an existing session 291 290 -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestProp.cpp
r31016 r31019 88 88 { 89 89 /* open a session for the VM - new or existing */ 90 SessionType_T st; 91 CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1); 90 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1); 92 91 93 92 /* get the mutable session machine */ … … 154 153 { 155 154 /* open a session for the VM - new or existing */ 156 SessionType_T st; 157 CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1); 155 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1); 158 156 159 157 /* get the mutable session machine */ … … 215 213 { 216 214 /* open a session for the VM - new or existing */ 217 SessionType_T st; 218 CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1); 215 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1); 219 216 220 217 /* get the mutable session machine */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp
r31016 r31019 2135 2135 2136 2136 /* open an existing session for the VM */ 2137 SessionType_T st; 2138 rc = machine->LockForSession(a->session, true /* fPermitShared */, &st); 2137 rc = machine->LockMachine(a->session, LockType_Shared); 2139 2138 if (SUCCEEDED(rc)) 2140 2139 /* get the session machine */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageMisc.cpp
r31016 r31019 418 418 { 419 419 /* we have to open a session for this task */ 420 SessionType_T st; 421 CHECK_ERROR_BREAK(machine, LockForSession(a->session, false /* fPermitShared */, &st)); 420 CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write)); 422 421 do 423 422 { … … 453 452 { 454 453 /* we have to open a session for this task */ 455 SessionType_T st; 456 CHECK_ERROR_BREAK(machine, LockForSession(a->session, false /* fPermitShared */, &st)); 454 CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Write)); 457 455 do 458 456 { … … 728 726 729 727 /* open an existing session for the VM */ 730 SessionType_T st; 731 CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1); 728 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1); 732 729 /* get the session machine */ 733 730 CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1); … … 744 741 /* open a session for the VM */ 745 742 SessionType_T st; 746 CHECK_ERROR_RET(machine, Lock ForSession(a->session, false /* fPermitShared */, &st), 1);743 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1); 747 744 748 745 /* get the mutable session machine */ … … 794 791 795 792 /* open an existing session for the VM */ 796 SessionType_T st; 797 CHECK_ERROR_RET(machine, LockForSession(a->session, true /* fPermitShared */, &st), 1); 793 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1); 798 794 /* get the session machine */ 799 795 CHECK_ERROR_RET(a->session, COMGETTER(Machine)(machine.asOutParam()), 1); … … 809 805 { 810 806 /* open a session for the VM */ 811 SessionType_T st; 812 CHECK_ERROR_RET(machine, LockForSession(a->session, false /* fPermitShared */, &st), 1); 807 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1); 813 808 814 809 /* get the mutable session machine */ … … 880 875 881 876 /* open an existing session for the VM. */ 882 SessionType_T st; 883 CHECK_ERROR(machine, LockForSession(a->session, true /* fPermitShared */, &st)); 877 CHECK_ERROR(machine, LockMachine(a->session, LockType_Shared)); 884 878 if (SUCCEEDED(rc)) 885 879 { -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
r31016 r31019 312 312 313 313 /* open a session for the VM */ 314 SessionType_T st; 315 CHECK_ERROR_RET(machine, LockForSession(a->session, false /* fPermitShared */, &st), 1); 314 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1); 316 315 317 316 /* get the mutable session machine */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageSnapshot.cpp
r31016 r31019 240 240 { 241 241 /* we have to open a session for this task (new or shared) */ 242 SessionType_T st; 243 rc = pMachine->LockForSession(a->session, true /* fPermitShared */, &st); 242 rc = pMachine->LockMachine(a->session, LockType_Shared); 244 243 ComPtr<IConsole> console; 245 244 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam())); -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp
r31016 r31019 173 173 174 174 /* open a session for the VM (new or shared) */ 175 SessionType_T type; 176 rc = machine->LockForSession(a->session, true /* fPermitShared */, &type); 177 bool fRunTime = (type == SessionType_Shared); 175 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1); 176 SessionType_T st; 177 CHECK_ERROR_RET(a->session, COMGETTER(Type)(&st), 1); 178 bool fRunTime = (st == SessionType_Shared); 179 178 180 if (fRunTime && !RTStrICmp(pszType, "hdd")) 179 181 { … … 755 757 756 758 /* open a session for the VM */ 757 SessionType_T st; 758 CHECK_ERROR_RET(machine, LockForSession(a->session, false /* fPermitShared */, &st), 1); 759 CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Write), 1); 759 760 760 761 /* get the mutable session machine */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp
r31016 r31019 417 417 { 418 418 /* open a session for the VM */ 419 SessionType_T st; 420 CHECK_ERROR_RET(cmd.mMachine, LockForSession(a->session, false /* fPermitShared */, &st), 1); 419 CHECK_ERROR_RET(cmd.mMachine, LockMachine(a->session, LockType_Write), 1); 421 420 /* get the mutable session machine */ 422 421 a->session->COMGETTER(Machine)(cmd.mMachine.asOutParam()); -
trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
r31016 r31019 1365 1365 AssertReleaseRC(vrc); 1366 1366 1367 SessionType_T st; 1368 rc = pMachine->LockForSession(session, false /* fPermitShared */, &st); 1367 rc = pMachine->LockMachine(session, LockType_Write); 1369 1368 if (FAILED(rc)) 1370 1369 { -
trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp
r31008 r31019 2179 2179 if (!foundMachine.isNull()) 2180 2180 { 2181 KSessionType t = foundMachine.LockForSession(session, aExisting /* fPermitShared */); 2182 if (t == KSessionType_Shared) 2181 foundMachine.LockMachine(session, 2182 (aExisting) ? KLockType_Shared : KLockType_Write); 2183 if (session.GetType() == KSessionType_Shared) 2183 2184 { 2184 2185 CMachine machine = session.GetMachine(); -
trunk/src/VBox/Frontends/VirtualBox/src/selector/UIVMPreviewWindow.cpp
r31008 r31019 245 245 { 246 246 CVirtualBox vbox = vboxGlobal().virtualBox(); 247 m_machine.Lock ForSession(session, true /* fPermitShared */);247 m_machine.LockMachine(session, KLockType_Shared); 248 248 if (vbox.isOk()) 249 249 { -
trunk/src/VBox/Frontends/VirtualBox/src/selector/VBoxSelectorWnd.cpp
r31008 r31019 797 797 CMachine foundMachine = vbox.GetMachine(id); 798 798 if (!foundMachine.isNull()) 799 foundMachine.Lock ForSession(session, false /* fPermitShared */);799 foundMachine.LockMachine(session, KLockType_Write); 800 800 if (!vbox.isOk()) 801 801 { -
trunk/src/VBox/Main/ApplianceImplImport.cpp
r31008 r31019 1233 1233 { 1234 1234 const MyHardDiskAttachment &mhda = *itM; 1235 rc2 = mhda.pMachine->Lock ForSession(stack.pSession, false /* fPermitShared */, NULL);1235 rc2 = mhda.pMachine->LockMachine(stack.pSession, LockType_Write); 1236 1236 if (SUCCEEDED(rc2)) 1237 1237 { … … 1760 1760 { 1761 1761 // to attach things we need to open a session for the new machine 1762 rc = pNewMachine->Lock ForSession(stack.pSession, false /* fPermitShared */, NULL);1762 rc = pNewMachine->LockMachine(stack.pSession, LockType_Write); 1763 1763 if (FAILED(rc)) DebugBreakThrow(rc); 1764 1764 stack.fSessionOpen = true; … … 1872 1872 { 1873 1873 // to attach things we need to open a session for the new machine 1874 rc = pNewMachine->Lock ForSession(stack.pSession, false /* fPermitShared */, NULL);1874 rc = pNewMachine->LockMachine(stack.pSession, LockType_Write); 1875 1875 if (FAILED(rc)) DebugBreakThrow(rc); 1876 1876 stack.fSessionOpen = true; -
trunk/src/VBox/Main/MachineImpl.cpp
r31008 r31019 2681 2681 * @note Locks objects! 2682 2682 */ 2683 STDMETHODIMP Machine::LockForSession(ISession *aSession, 2684 BOOL fPermitShared, 2685 SessionType_T *pSessionType) 2683 STDMETHODIMP Machine::LockMachine(ISession *aSession, 2684 LockType_T lockType) 2686 2685 { 2687 2686 CheckComArgNotNull(aSession); … … 2700 2699 2701 2700 /* get the IInternalSessionControl interface */ 2702 ComPtr<IInternalSessionControl> control = aSession;2703 ComAssertMsgRet(!! control, ("No IInternalSessionControl interface"),2701 ComPtr<IInternalSessionControl> pSessionControl = aSession; 2702 ComAssertMsgRet(!!pSessionControl, ("No IInternalSessionControl interface"), 2704 2703 E_INVALIDARG); 2705 2704 2706 rc = openSession(control); 2707 2708 if (FAILED(rc) && fPermitShared) 2709 // try again @todo r=dj check exact error code! 2710 rc = openExistingSession(control); 2705 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); 2706 2707 if (!mData->mRegistered) 2708 return setError(E_UNEXPECTED, 2709 tr("The machine '%ls' is not registered"), 2710 mUserData->mName.raw()); 2711 2712 LogFlowThisFunc(("mSession.mState=%s\n", Global::stringifySessionState(mData->mSession.mState))); 2713 2714 /* Hack: in case the session is closing and there is a progress object 2715 * which allows waiting for the session to be closed, take the opportunity 2716 * and do a limited wait (max. 1 second). This helps a lot when the system 2717 * is busy and thus session closing can take a little while. */ 2718 if ( mData->mSession.mState == SessionState_Unlocking 2719 && mData->mSession.mProgress) 2720 { 2721 alock.release(); 2722 mData->mSession.mProgress->WaitForCompletion(1000); 2723 alock.acquire(); 2724 LogFlowThisFunc(("after waiting: mSession.mState=%s\n", Global::stringifySessionState(mData->mSession.mState))); 2725 } 2726 2727 // try again now 2728 if ( mData->mSession.mState == SessionState_Locked 2729 || mData->mSession.mState == SessionState_Unlocking 2730 ) 2731 { 2732 // If the machine is write-locked already (i.e. SessionMachine exists) and 2733 // caller permits sharing, then try to do that now 2734 if ( (mData->mSession.mState == SessionState_Locked) 2735 && (lockType == LockType_Shared) 2736 ) 2737 { 2738 ComAssertRet(!mData->mSession.mDirectControl.isNull(), E_FAIL); 2739 2740 // copy member variables before leaving lock 2741 ComPtr<IInternalSessionControl> pDirectControl = mData->mSession.mDirectControl; 2742 ComObjPtr<SessionMachine> pSessionMachine = mData->mSession.mMachine; 2743 AssertReturn(!pSessionMachine.isNull(), E_FAIL); 2744 2745 /* 2746 * Leave the lock before calling the client process. It's safe here 2747 * since the only thing to do after we get the lock again is to add 2748 * the remote control to the list (which doesn't directly influence 2749 * anything). 2750 */ 2751 alock.leave(); 2752 2753 // get the console from the direct session (this is a remote call) 2754 ComPtr<IConsole> pConsole; 2755 LogFlowThisFunc(("Calling GetRemoteConsole()...\n")); 2756 rc = pDirectControl->GetRemoteConsole(pConsole.asOutParam()); 2757 LogFlowThisFunc(("GetRemoteConsole() returned %08X\n", rc)); 2758 if (FAILED(rc)) 2759 /* The failure may occur w/o any error info (from RPC), so provide one */ 2760 return setError(VBOX_E_VM_ERROR, 2761 tr("Failed to get a console object from the direct session (%Rrc)"), rc); 2762 2763 ComAssertRet(!pConsole.isNull(), E_FAIL); 2764 2765 /* attach the remote session to the machine */ 2766 LogFlowThisFunc(("Calling AssignRemoteMachine()...\n")); 2767 rc = pSessionControl->AssignRemoteMachine(pSessionMachine, pConsole); 2768 LogFlowThisFunc(("AssignRemoteMachine() returned %08X\n", rc)); 2769 2770 /* The failure may occur w/o any error info (from RPC), so provide one */ 2771 if (FAILED(rc)) 2772 return setError(VBOX_E_VM_ERROR, 2773 tr("Failed to assign the machine to the session (%Rrc)"), 2774 rc); 2775 alock.enter(); 2776 2777 /* need to revalidate the state after entering the lock again */ 2778 if (mData->mSession.mState != SessionState_Locked) 2779 { 2780 pSessionControl->Uninitialize(); 2781 return setError(VBOX_E_INVALID_SESSION_STATE, 2782 tr("The machine '%ls' was unlocked unexpectedly while attempting to share its session"), 2783 mUserData->mName.raw()); 2784 } 2785 2786 // add the caller's control to the list 2787 mData->mSession.mRemoteControls.push_back(pSessionControl); 2788 } 2789 else 2790 // still unlocking, or caller has not permitted sharing: 2791 return setError(VBOX_E_INVALID_OBJECT_STATE, 2792 tr("The machine '%ls' is already locked for a session (or being unlocked)"), 2793 mUserData->mName.raw()); 2794 } 2795 else 2796 { 2797 // no lock exists or sharing not permitted: then create the session machine 2798 2799 /* may not be busy */ 2800 AssertReturn(!Global::IsOnlineOrTransient(mData->mMachineState), E_FAIL); 2801 2802 // get the caller's session PID 2803 RTPROCESS pid = NIL_RTPROCESS; 2804 AssertCompile(sizeof(ULONG) == sizeof(RTPROCESS)); 2805 pSessionControl->GetPID((ULONG*)&pid); 2806 Assert(pid != NIL_RTPROCESS); 2807 2808 if (mData->mSession.mState == SessionState_Spawning) 2809 { 2810 /* This machine is awaiting for a spawning session to be opened, so 2811 * reject any other open attempts from processes other than one 2812 * started by #openRemoteSession(). */ 2813 2814 LogFlowThisFunc(("mSession.mPid=%d(0x%x)\n", mData->mSession.mPid, mData->mSession.mPid)); 2815 LogFlowThisFunc(("session.pid=%d(0x%x)\n", pid, pid)); 2816 2817 if (mData->mSession.mPid != pid) 2818 return setError(E_ACCESSDENIED, 2819 tr("An unexpected process (PID=0x%08X) has tried to lock the " 2820 "machine '%ls', while only the process started by launchVMProcess (PID=0x%08X) is allowed"), 2821 pid, mUserData->mName.raw(), mData->mSession.mPid); 2822 } 2823 2824 // create the mutable SessionMachine from the current machine 2825 ComObjPtr<SessionMachine> sessionMachine; 2826 sessionMachine.createObject(); 2827 rc = sessionMachine->init(this); 2828 AssertComRC(rc); 2829 2830 /* NOTE: doing return from this function after this point but 2831 * before the end is forbidden since it may call SessionMachine::uninit() 2832 * (through the ComObjPtr's destructor) which requests the VirtualBox write 2833 * lock while still holding the Machine lock in alock so that a deadlock 2834 * is possible due to the wrong lock order. */ 2835 2836 if (SUCCEEDED(rc)) 2837 { 2838 /* 2839 * Set the session state to Spawning to protect against subsequent 2840 * attempts to open a session and to unregister the machine after 2841 * we leave the lock. 2842 */ 2843 SessionState_T origState = mData->mSession.mState; 2844 mData->mSession.mState = SessionState_Spawning; 2845 2846 /* 2847 * Leave the lock before calling the client process -- it will call 2848 * Machine/SessionMachine methods. Leaving the lock here is quite safe 2849 * because the state is Spawning, so that openRemotesession() and 2850 * openExistingSession() calls will fail. This method, called before we 2851 * enter the lock again, will fail because of the wrong PID. 2852 * 2853 * Note that mData->mSession.mRemoteControls accessed outside 2854 * the lock may not be modified when state is Spawning, so it's safe. 2855 */ 2856 alock.leave(); 2857 2858 LogFlowThisFunc(("Calling AssignMachine()...\n")); 2859 rc = pSessionControl->AssignMachine(sessionMachine); 2860 LogFlowThisFunc(("AssignMachine() returned %08X\n", rc)); 2861 2862 /* The failure may occur w/o any error info (from RPC), so provide one */ 2863 if (FAILED(rc)) 2864 setError(VBOX_E_VM_ERROR, 2865 tr("Failed to assign the machine to the session (%Rrc)"), rc); 2866 2867 if ( SUCCEEDED(rc) 2868 && origState == SessionState_Spawning 2869 ) 2870 { 2871 /* complete the remote session initialization */ 2872 2873 /* get the console from the direct session */ 2874 ComPtr<IConsole> console; 2875 rc = pSessionControl->GetRemoteConsole(console.asOutParam()); 2876 ComAssertComRC(rc); 2877 2878 if (SUCCEEDED(rc) && !console) 2879 { 2880 ComAssert(!!console); 2881 rc = E_FAIL; 2882 } 2883 2884 /* assign machine & console to the remote session */ 2885 if (SUCCEEDED(rc)) 2886 { 2887 /* 2888 * after openRemoteSession(), the first and the only 2889 * entry in remoteControls is that remote session 2890 */ 2891 LogFlowThisFunc(("Calling AssignRemoteMachine()...\n")); 2892 rc = mData->mSession.mRemoteControls.front()->AssignRemoteMachine(sessionMachine, console); 2893 LogFlowThisFunc(("AssignRemoteMachine() returned %08X\n", rc)); 2894 2895 /* The failure may occur w/o any error info (from RPC), so provide one */ 2896 if (FAILED(rc)) 2897 setError(VBOX_E_VM_ERROR, 2898 tr("Failed to assign the machine to the remote session (%Rrc)"), rc); 2899 } 2900 2901 if (FAILED(rc)) 2902 pSessionControl->Uninitialize(); 2903 } 2904 2905 /* enter the lock again */ 2906 alock.enter(); 2907 2908 /* Restore the session state */ 2909 mData->mSession.mState = origState; 2910 } 2911 2912 /* finalize spawning anyway (this is why we don't return on errors above) */ 2913 if (mData->mSession.mState == SessionState_Spawning) 2914 { 2915 /* Note that the progress object is finalized later */ 2916 /** @todo Consider checking mData->mSession.mProgress for cancellation 2917 * around here. */ 2918 2919 /* We don't reset mSession.mPid here because it is necessary for 2920 * SessionMachine::uninit() to reap the child process later. */ 2921 2922 if (FAILED(rc)) 2923 { 2924 /* Close the remote session, remove the remote control from the list 2925 * and reset session state to Closed (@note keep the code in sync 2926 * with the relevant part in openSession()). */ 2927 2928 Assert(mData->mSession.mRemoteControls.size() == 1); 2929 if (mData->mSession.mRemoteControls.size() == 1) 2930 { 2931 ErrorInfoKeeper eik; 2932 mData->mSession.mRemoteControls.front()->Uninitialize(); 2933 } 2934 2935 mData->mSession.mRemoteControls.clear(); 2936 mData->mSession.mState = SessionState_Unlocked; 2937 } 2938 } 2939 else 2940 { 2941 /* memorize PID of the directly opened session */ 2942 if (SUCCEEDED(rc)) 2943 mData->mSession.mPid = pid; 2944 } 2945 2946 if (SUCCEEDED(rc)) 2947 { 2948 /* memorize the direct session control and cache IUnknown for it */ 2949 mData->mSession.mDirectControl = pSessionControl; 2950 mData->mSession.mState = SessionState_Locked; 2951 /* associate the SessionMachine with this Machine */ 2952 mData->mSession.mMachine = sessionMachine; 2953 2954 /* request an IUnknown pointer early from the remote party for later 2955 * identity checks (it will be internally cached within mDirectControl 2956 * at least on XPCOM) */ 2957 ComPtr<IUnknown> unk = mData->mSession.mDirectControl; 2958 NOREF(unk); 2959 } 2960 2961 /* Leave the lock since SessionMachine::uninit() locks VirtualBox which 2962 * would break the lock order */ 2963 alock.leave(); 2964 2965 /* uninitialize the created session machine on failure */ 2966 if (FAILED(rc)) 2967 sessionMachine->uninit(); 2968 2969 } 2711 2970 2712 2971 if (SUCCEEDED(rc)) … … 2720 2979 /* fire an event */ 2721 2980 mParent->onSessionStateChange(getId(), SessionState_Locked); 2722 2723 // return session type to caller2724 if (pSessionType)2725 aSession->COMGETTER(Type)(pSessionType);2726 2981 } 2727 2982 … … 5354 5609 5355 5610 /** 5356 * @note Locks this object for writing, calls the client process (outside the5357 * lock).5358 */5359 HRESULT Machine::openSession(IInternalSessionControl *aControl)5360 {5361 LogFlowThisFuncEnter();5362 5363 AssertReturn(aControl, E_FAIL);5364 5365 AutoCaller autoCaller(this);5366 if (FAILED(autoCaller.rc()))5367 return autoCaller.rc();5368 5369 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);5370 5371 if (!mData->mRegistered)5372 return setError(E_UNEXPECTED,5373 tr("The machine '%ls' is not registered"),5374 mUserData->mName.raw());5375 5376 LogFlowThisFunc(("mSession.mState=%s\n", Global::stringifySessionState(mData->mSession.mState)));5377 5378 /* Hack: in case the session is closing and there is a progress object5379 * which allows waiting for the session to be closed, take the opportunity5380 * and do a limited wait (max. 1 second). This helps a lot when the system5381 * is busy and thus session closing can take a little while. */5382 if ( mData->mSession.mState == SessionState_Unlocking5383 && mData->mSession.mProgress)5384 {5385 alock.leave();5386 mData->mSession.mProgress->WaitForCompletion(1000);5387 alock.enter();5388 LogFlowThisFunc(("after waiting: mSession.mState=%s\n", Global::stringifySessionState(mData->mSession.mState)));5389 }5390 5391 if ( mData->mSession.mState == SessionState_Locked5392 || mData->mSession.mState == SessionState_Unlocking5393 )5394 return setError(VBOX_E_INVALID_OBJECT_STATE,5395 tr("The machine '%ls' is already locked for a session (or being unlocked)"),5396 mUserData->mName.raw());5397 5398 /* may not be busy */5399 AssertReturn(!Global::IsOnlineOrTransient(mData->mMachineState), E_FAIL);5400 5401 /* get the session PID */5402 RTPROCESS pid = NIL_RTPROCESS;5403 AssertCompile(sizeof(ULONG) == sizeof(RTPROCESS));5404 aControl->GetPID((ULONG *) &pid);5405 Assert(pid != NIL_RTPROCESS);5406 5407 if (mData->mSession.mState == SessionState_Spawning)5408 {5409 /* This machine is awaiting for a spawning session to be opened, so5410 * reject any other open attempts from processes other than one5411 * started by #openRemoteSession(). */5412 5413 LogFlowThisFunc(("mSession.mPid=%d(0x%x)\n",5414 mData->mSession.mPid, mData->mSession.mPid));5415 LogFlowThisFunc(("session.pid=%d(0x%x)\n", pid, pid));5416 5417 if (mData->mSession.mPid != pid)5418 return setError(E_ACCESSDENIED,5419 tr("An unexpected process (PID=0x%08X) has tried to lock the "5420 "machine '%ls', while only the process started by launchVMProcess (PID=0x%08X) is allowed"),5421 pid, mUserData->mName.raw(), mData->mSession.mPid);5422 }5423 5424 /* create a SessionMachine object */5425 ComObjPtr<SessionMachine> sessionMachine;5426 sessionMachine.createObject();5427 HRESULT rc = sessionMachine->init(this);5428 AssertComRC(rc);5429 5430 /* NOTE: doing return from this function after this point but5431 * before the end is forbidden since it may call SessionMachine::uninit()5432 * (through the ComObjPtr's destructor) which requests the VirtualBox write5433 * lock while still holding the Machine lock in alock so that a deadlock5434 * is possible due to the wrong lock order. */5435 5436 if (SUCCEEDED(rc))5437 {5438 /*5439 * Set the session state to Spawning to protect against subsequent5440 * attempts to open a session and to unregister the machine after5441 * we leave the lock.5442 */5443 SessionState_T origState = mData->mSession.mState;5444 mData->mSession.mState = SessionState_Spawning;5445 5446 /*5447 * Leave the lock before calling the client process -- it will call5448 * Machine/SessionMachine methods. Leaving the lock here is quite safe5449 * because the state is Spawning, so that openRemotesession() and5450 * openExistingSession() calls will fail. This method, called before we5451 * enter the lock again, will fail because of the wrong PID.5452 *5453 * Note that mData->mSession.mRemoteControls accessed outside5454 * the lock may not be modified when state is Spawning, so it's safe.5455 */5456 alock.leave();5457 5458 LogFlowThisFunc(("Calling AssignMachine()...\n"));5459 rc = aControl->AssignMachine(sessionMachine);5460 LogFlowThisFunc(("AssignMachine() returned %08X\n", rc));5461 5462 /* The failure may occur w/o any error info (from RPC), so provide one */5463 if (FAILED(rc))5464 setError(VBOX_E_VM_ERROR,5465 tr("Failed to assign the machine to the session (%Rrc)"), rc);5466 5467 if (SUCCEEDED(rc) && origState == SessionState_Spawning)5468 {5469 /* complete the remote session initialization */5470 5471 /* get the console from the direct session */5472 ComPtr<IConsole> console;5473 rc = aControl->GetRemoteConsole(console.asOutParam());5474 ComAssertComRC(rc);5475 5476 if (SUCCEEDED(rc) && !console)5477 {5478 ComAssert(!!console);5479 rc = E_FAIL;5480 }5481 5482 /* assign machine & console to the remote session */5483 if (SUCCEEDED(rc))5484 {5485 /*5486 * after openRemoteSession(), the first and the only5487 * entry in remoteControls is that remote session5488 */5489 LogFlowThisFunc(("Calling AssignRemoteMachine()...\n"));5490 rc = mData->mSession.mRemoteControls.front()->5491 AssignRemoteMachine(sessionMachine, console);5492 LogFlowThisFunc(("AssignRemoteMachine() returned %08X\n", rc));5493 5494 /* The failure may occur w/o any error info (from RPC), so provide one */5495 if (FAILED(rc))5496 setError(VBOX_E_VM_ERROR,5497 tr("Failed to assign the machine to the remote session (%Rrc)"), rc);5498 }5499 5500 if (FAILED(rc))5501 aControl->Uninitialize();5502 }5503 5504 /* enter the lock again */5505 alock.enter();5506 5507 /* Restore the session state */5508 mData->mSession.mState = origState;5509 }5510 5511 /* finalize spawning anyway (this is why we don't return on errors above) */5512 if (mData->mSession.mState == SessionState_Spawning)5513 {5514 /* Note that the progress object is finalized later */5515 /** @todo Consider checking mData->mSession.mProgress for cancellation5516 * around here. */5517 5518 /* We don't reset mSession.mPid here because it is necessary for5519 * SessionMachine::uninit() to reap the child process later. */5520 5521 if (FAILED(rc))5522 {5523 /* Close the remote session, remove the remote control from the list5524 * and reset session state to Closed (@note keep the code in sync5525 * with the relevant part in openSession()). */5526 5527 Assert(mData->mSession.mRemoteControls.size() == 1);5528 if (mData->mSession.mRemoteControls.size() == 1)5529 {5530 ErrorInfoKeeper eik;5531 mData->mSession.mRemoteControls.front()->Uninitialize();5532 }5533 5534 mData->mSession.mRemoteControls.clear();5535 mData->mSession.mState = SessionState_Unlocked;5536 }5537 }5538 else5539 {5540 /* memorize PID of the directly opened session */5541 if (SUCCEEDED(rc))5542 mData->mSession.mPid = pid;5543 }5544 5545 if (SUCCEEDED(rc))5546 {5547 /* memorize the direct session control and cache IUnknown for it */5548 mData->mSession.mDirectControl = aControl;5549 mData->mSession.mState = SessionState_Locked;5550 /* associate the SessionMachine with this Machine */5551 mData->mSession.mMachine = sessionMachine;5552 5553 /* request an IUnknown pointer early from the remote party for later5554 * identity checks (it will be internally cached within mDirectControl5555 * at least on XPCOM) */5556 ComPtr<IUnknown> unk = mData->mSession.mDirectControl;5557 NOREF(unk);5558 }5559 5560 /* Leave the lock since SessionMachine::uninit() locks VirtualBox which5561 * would break the lock order */5562 alock.leave();5563 5564 /* uninitialize the created session machine on failure */5565 if (FAILED(rc))5566 sessionMachine->uninit();5567 5568 LogFlowThisFunc(("rc=%Rhrc\n", rc));5569 LogFlowThisFuncLeave();5570 return rc;5571 }5572 5573 /**5574 5611 * @note Locks this object for writing, calls the client process 5575 5612 * (inside the lock). … … 5797 5834 mData->mSession.mState = SessionState_Spawning; 5798 5835 mData->mSession.mType = strType; 5799 5800 LogFlowThisFuncLeave();5801 return S_OK;5802 }5803 5804 5805 /**5806 * @note Locks this object for writing, calls the client process5807 * (outside the lock).5808 */5809 HRESULT Machine::openExistingSession(IInternalSessionControl *aControl)5810 {5811 LogFlowThisFuncEnter();5812 5813 AssertReturn(aControl, E_FAIL);5814 5815 AutoCaller autoCaller(this);5816 if (FAILED(autoCaller.rc())) return autoCaller.rc();5817 5818 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);5819 5820 if (!mData->mRegistered)5821 return setError(E_UNEXPECTED,5822 tr("The machine '%ls' is not registered"),5823 mUserData->mName.raw());5824 5825 LogFlowThisFunc(("mSession.state=%s\n", Global::stringifySessionState(mData->mSession.mState)));5826 5827 if (mData->mSession.mState != SessionState_Locked)5828 return setError(VBOX_E_INVALID_SESSION_STATE,5829 tr("The machine '%ls' is not currently locked for a session"),5830 mUserData->mName.raw());5831 5832 ComAssertRet(!mData->mSession.mDirectControl.isNull(), E_FAIL);5833 5834 // copy member variables before leaving lock5835 ComPtr<IInternalSessionControl> pDirectControl = mData->mSession.mDirectControl;5836 ComObjPtr<SessionMachine> pSessionMachine = mData->mSession.mMachine;5837 AssertReturn(!pSessionMachine.isNull(), E_FAIL);5838 5839 /*5840 * Leave the lock before calling the client process. It's safe here5841 * since the only thing to do after we get the lock again is to add5842 * the remote control to the list (which doesn't directly influence5843 * anything).5844 */5845 alock.leave();5846 5847 // get the console from the direct session (this is a remote call)5848 ComPtr<IConsole> pConsole;5849 LogFlowThisFunc(("Calling GetRemoteConsole()...\n"));5850 HRESULT rc = pDirectControl->GetRemoteConsole(pConsole.asOutParam());5851 LogFlowThisFunc(("GetRemoteConsole() returned %08X\n", rc));5852 if (FAILED (rc))5853 /* The failure may occur w/o any error info (from RPC), so provide one */5854 return setError(VBOX_E_VM_ERROR,5855 tr("Failed to get a console object from the direct session (%Rrc)"), rc);5856 5857 ComAssertRet(!pConsole.isNull(), E_FAIL);5858 5859 /* attach the remote session to the machine */5860 LogFlowThisFunc(("Calling AssignRemoteMachine()...\n"));5861 rc = aControl->AssignRemoteMachine(pSessionMachine, pConsole);5862 LogFlowThisFunc(("AssignRemoteMachine() returned %08X\n", rc));5863 5864 /* The failure may occur w/o any error info (from RPC), so provide one */5865 if (FAILED(rc))5866 return setError(VBOX_E_VM_ERROR,5867 tr("Failed to assign the machine to the session (%Rrc)"),5868 rc);5869 5870 alock.enter();5871 5872 /* need to revalidate the state after entering the lock again */5873 if (mData->mSession.mState != SessionState_Locked)5874 {5875 aControl->Uninitialize();5876 5877 return setError(VBOX_E_INVALID_SESSION_STATE,5878 tr("The machine '%ls' is not currently locked for a session"),5879 mUserData->mName.raw());5880 }5881 5882 /* store the control in the list */5883 mData->mSession.mRemoteControls.push_back(aControl);5884 5836 5885 5837 LogFlowThisFuncLeave(); -
trunk/src/VBox/Main/SessionImpl.cpp
r31008 r31019 278 278 AssertReturn(mState != SessionState_Unlocked, VBOX_E_INVALID_VM_STATE); 279 279 280 AssertMsgReturn(mType == SessionType_ Direct&& !!mConsole,280 AssertMsgReturn(mType == SessionType_WriteLock && !!mConsole, 281 281 ("This is not a direct session!\n"), 282 282 VBOX_E_INVALID_OBJECT_STATE); … … 345 345 if (SUCCEEDED(rc)) 346 346 { 347 mType = SessionType_ Direct;347 mType = SessionType_WriteLock; 348 348 mState = SessionState_Locked; 349 349 } … … 458 458 459 459 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 460 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);460 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 461 461 462 462 AssertReturn(!mControl.isNull(), E_FAIL); … … 522 522 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 523 523 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 524 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);524 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 525 525 526 526 return mConsole->onNetworkAdapterChange(networkAdapter, changeAdapter); … … 536 536 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 537 537 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 538 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);538 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 539 539 540 540 return mConsole->onSerialPortChange(serialPort); … … 550 550 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 551 551 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 552 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);552 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 553 553 554 554 return mConsole->onParallelPortChange(parallelPort); … … 564 564 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 565 565 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 566 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);566 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 567 567 568 568 return mConsole->onStorageControllerChange(); … … 578 578 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 579 579 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 580 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);580 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 581 581 582 582 return mConsole->onMediumChange(aMediumAttachment, aForce); … … 592 592 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 593 593 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 594 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);594 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 595 595 596 596 return mConsole->onCPUChange(aCPU, aRemove); … … 606 606 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 607 607 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 608 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);608 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 609 609 610 610 return mConsole->onVRDPServerChange(aRestart); … … 620 620 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 621 621 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 622 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);622 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 623 623 624 624 return mConsole->onUSBControllerChange(); … … 634 634 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 635 635 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 636 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);636 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 637 637 638 638 return mConsole->onSharedFolderChange(aGlobal); … … 650 650 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 651 651 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 652 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);652 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 653 653 654 654 return mConsole->onUSBDeviceAttach(aDevice, aError, aMaskedIfs); … … 665 665 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 666 666 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 667 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);667 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 668 668 669 669 return mConsole->onUSBDeviceDetach(aId, aError); … … 677 677 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 678 678 679 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);679 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 680 680 681 681 if (mState != SessionState_Locked) … … 704 704 tr("Machine is not locked by session (session state: %s)."), 705 705 Global::stringifySessionState(mState)); 706 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);706 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 707 707 CheckComArgStrNotEmptyOrNull(aName); 708 708 if (!aIsSetter && !VALID_PTR(aRetValue)) … … 741 741 tr("Machine is not locked by session (session state: %s)."), 742 742 Global::stringifySessionState(mState)); 743 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);743 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 744 744 if (!VALID_PTR(aPatterns) && (aPatterns != NULL)) 745 745 return E_POINTER; … … 777 777 tr("Machine is not locked by session (session state: %s)."), 778 778 Global::stringifySessionState(mState)); 779 AssertReturn(mType == SessionType_ Direct, VBOX_E_INVALID_OBJECT_STATE);779 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 780 780 CheckComArgNotNull(aMediumAttachment); 781 781 CheckComArgSafeArrayNotNull(aChildrenToReparent); … … 847 847 mState = SessionState_Unlocking; 848 848 849 if (mType == SessionType_ Direct)849 if (mType == SessionType_WriteLock) 850 850 { 851 851 mConsole->uninit(); … … 894 894 * VirtualBoxBase::addCaller. 895 895 */ 896 if (mType != SessionType_ Direct&& (rc == E_UNEXPECTED || rc == E_ACCESSDENIED))896 if (mType != SessionType_WriteLock && (rc == E_UNEXPECTED || rc == E_ACCESSDENIED)) 897 897 rc = S_OK; 898 898 … … 902 902 mControl.setNull(); 903 903 904 if (mType == SessionType_ Direct)904 if (mType == SessionType_WriteLock) 905 905 { 906 906 releaseIPCSemaphore(); -
trunk/src/VBox/Main/VirtualBoxImpl.cpp
r31008 r31019 3723 3723 /** 3724 3724 * Thread function that watches the termination of all client processes 3725 * that have opened sessions using IMachine::Lock ForSession()3725 * that have opened sessions using IMachine::LockMachine() 3726 3726 */ 3727 3727 // static -
trunk/src/VBox/Main/glue/glue-java.xsl
r31008 r31019 2497 2497 { 2498 2498 ISession s = getSessionObject(); 2499 m.lock ForSession(s, true /* fPermitShared */);2499 m.lockMachine(s, LockType.Shared); 2500 2500 return s; 2501 2501 } … … 3459 3459 { 3460 3460 ISession s = getSessionObject(); 3461 m.lock ForSession(s, true /* fPermitShared */);3461 m.lockMachine(s, LockType.Shared); 3462 3462 return s; 3463 3463 } -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r31008 r31019 818 818 currently locked for this session, and the mutable machine object 819 819 can be found in the <link to="ISession::machine"/> attribute 820 (see <link to="IMachine::lock ForSession" /> for details).820 (see <link to="IMachine::lockMachine" /> for details). 821 821 </desc> 822 822 </const> … … 825 825 A new process is being spawned for the machine as a result of 826 826 <link to="IMachine::launchVMProcess"/> call. This state also occurs 827 as a short transient state during an <link to="IMachine::lock ForSession"/>827 as a short transient state during an <link to="IMachine::lockMachine"/> 828 828 call. 829 829 </desc> … … 906 906 907 907 <enum 908 name="LockType" 909 uuid="138b53f8-db4b-47c5-b32b-4ef52f769413" 910 > 911 <desc> 912 Used with <link to="IMachine::lockMachine" />. 913 </desc> 914 <const name="Write" value="2"> 915 <desc>Lock the machine for writing.</desc> 916 </const> 917 <const name="Shared" value="1"> 918 <desc>Request only a shared read lock for remote-controlling the machine.</desc> 919 </const> 920 </enum> 921 922 <enum 908 923 name="SessionType" 909 924 uuid="A13C02CB-0C2C-421E-8317-AC0E8AAA153A" … … 917 932 <desc>Null value (never used by the API).</desc> 918 933 </const> 919 <const name=" Direct"value="1">920 <desc> 921 Direct session922 (used with <link to="IMachine::lockForSession"/>)934 <const name="WriteLock" value="1"> 935 <desc> 936 Session has acquired an exclusive write lock on a machine 937 using <link to="IMachine::lockMachine"/>. 923 938 </desc> 924 939 </const> 925 940 <const name="Remote" value="2"> 926 941 <desc> 927 Remote VM process928 (opened by <link to="IMachine::launchVMProcess"/>)942 Session has launched a VM process using 943 <link to="IMachine::launchVMProcess"/> 929 944 </desc> 930 945 </const> 931 946 <const name="Shared" value="3"> 932 947 <desc> 933 S hared session; remote link to an existing direct session opened934 by <link to="IMachine::lockForSession"/> with fPermitShared = true948 Session has obtained a link to another session using 949 <link to="IMachine::lockMachine"/> 935 950 </desc> 936 951 </const> … … 3655 3670 3656 3671 In order to change a machine setting, a session for this machine must be 3657 opened using one of the <link to="IMachine::lock ForSession" /> or3672 opened using one of the <link to="IMachine::lockMachine" /> or 3658 3673 <link to="IMachine::launchVMProcess"/> methods. After the 3659 3674 machine has been successfully locked for a session, a mutable machine object … … 3997 4012 same value as passed to the 3998 4013 <link to="IMachine::launchVMProcess"/> method in the 3999 @a type parameter. If the session was opened directly using4000 <link to="IMachine::lock ForSession" />, or if4014 @a type parameter. If the session was used with 4015 <link to="IMachine::lockMachine" />, or if 4001 4016 <link to="#sessionState"/> is SessionClosed, the value of this 4002 4017 attribute is an empty string. … … 4007 4022 <desc> 4008 4023 Identifier of the session process. This attribute contains the 4009 platform-dependent identifier of the process that has opened a 4010 direct session for this machine using the 4011 <link to="IMachine::lockForSession" /> call. The returned value 4012 is only valid if <link to="#sessionState"/> is SessionOpen or 4013 SessionClosing (i.e. a session is currently open or being 4014 closed) by the time this property is read. 4024 platform-dependent identifier of the process whose session was 4025 used with <link to="IMachine::lockMachine" /> call. The returned 4026 value is only valid if <link to="#sessionState"/> is Locked or 4027 Unlocking by the time this property is read. 4015 4028 </desc> 4016 4029 </attribute> … … 4193 4206 </attribute> 4194 4207 4195 <method name="lock ForSession">4208 <method name="lockMachine"> 4196 4209 <desc> 4197 4210 Locks the machine for the given session to enable the caller 4198 to make changes to the machine or start the VM. 4199 4200 A single machine can only be locked for a single sesseion 4201 at a time, protecting the VM from being manipulated by 4202 conflicting actions from different processes. Only after this 4203 method has been called, one can change all VM settings 4204 or execute the VM in the process space of the session object. 4205 See <link to="ISession">ISession</link> for details. 4206 4207 Locking the machine for a session creates a second copy of 4208 the IMachine object. It is this second object upon which 4209 changes can be made; in VirtualBox terminology, the second 4210 copy is "mutable". It is only this second, mutable machine 4211 object upon which you can call methods that change the 4212 machine state. After having called this method, you can 4213 obtain this second, mutable machine object using the 4214 <link to="ISession::machine" /> attribute. This way, you can 4215 also get access to the <link to="IConsole" /> object which 4216 controls VM execution. 4217 4218 <note>Unless you are writing a new VM frontend, you will not 4219 want to execute a VM in the current process. To spawn a new 4220 process that executes a VM, use <link to="IMachine::launchVMProcess" /> 4221 instead.</note> 4222 4223 One must always call <link to="ISession::close" /> to release the 4224 lock on the machine, or the machine's state will eventually be 4225 set to "Aborted". 4226 4227 In other words, to change settings on a machine, the following 4228 sequence is typically performed: 4211 to make changes to the machine or start the VM or control 4212 VM execution. 4213 4214 There are two ways to lock a machine for such uses: 4215 4216 <ul> 4217 <li>If you want to make changes to the machine settings, 4218 you must obtain an exclusive write lock on the machine 4219 by setting @a lockType to @c Write. 4220 4221 This will only succeed if no other process has locked 4222 the machine to prevent conflicting changes. Only after 4223 an exclusive write lock has been obtained using this method, one 4224 can change all VM settings or execute the VM in the process 4225 space of the session object. (Note that the latter is only of 4226 interest if you actually want to write a new front-end for 4227 virtual machines; but this API gets called internally by 4228 the existing front-ends such as VBoxHeadless and the VirtualBox 4229 GUI to acquire a write lock on the machine that they are running.) 4230 4231 On success, write-locking the machine for a session creates 4232 a second copy of the IMachine object. It is this second object 4233 upon which changes can be made; in VirtualBox terminology, the 4234 second copy is "mutable". It is only this second, mutable machine 4235 object upon which you can call methods that change the 4236 machine state. After having called this method, you can 4237 obtain this second, mutable machine object using the 4238 <link to="ISession::machine" /> attribute. 4239 </li> 4240 <li>If you only want to check the machine state or control 4241 machine execution without actually changing machine 4242 settings (e.g. to get access to VM statistics or take 4243 a snapshot or save the machine state), then set the 4244 @a lockType argument to @c Shared. 4245 4246 If no other session has obtained a lock, you will obtain an 4247 exclusive write lock as described above. However, if another 4248 session has already obtained such a lock, then a link to that 4249 existing session will be established which allows you 4250 to control that existing session. 4251 4252 To find out which type of lock was obtained, you can 4253 inspect <link to="ISession::type" />, which will have been 4254 set to either @c WriteLock or @c Shared. 4255 </li> 4256 </ul> 4257 4258 In either case, you can get access to the <link to="IConsole" /> 4259 object which controls VM execution. 4260 4261 Also in all of the above cases, one must always call <link to="ISession::close" /> 4262 to release the lock on the machine, or the machine's state will 4263 eventually be set to "Aborted". 4264 4265 To change settings on a machine, the following sequence is typically 4266 performed: 4229 4267 4230 4268 <ol> 4231 <li>Call this method (openSession) to have a machine locked for 4232 the current session.</li> 4269 <li>Call this method to obtain an exclusive write lock for the current session.</li> 4233 4270 4234 4271 <li>Obtain a mutable IMachine object from <link to="ISession::machine" />.</li> … … 4241 4278 </ol> 4242 4279 4243 If the @a fPermitShared parameter is set to true, this method will also4244 succeed on a machine which has already been locked by another session.4245 The caller will then be attached to that existing session, and its own4246 session will be marked as "Shared". While not all machine settings can4247 be changed in that case, an IConsole object will still be created which4248 provides to the caller some level of control over the VM execution, for4249 example to pause the machine. The number of such shared sessions per4250 machine is not limited by the API.4251 4252 The return value will then indicate whether a direct session was opened4253 (<link to="SessionType::Direct" />) or whether an existing direct session4254 was shared ((<link to="SessionType::Shared" />).4255 4256 If the @a fPermitShared parameter is @c false, then this can only4257 possibly return <link to="SessionType::Direct" />.4258 4259 4280 <result name="E_UNEXPECTED"> 4260 4281 Virtual machine not registered. … … 4275 4296 </desc> 4276 4297 </param> 4277 <param name="fPermitShared" type="boolean" dir="in"> 4278 <desc> 4279 Whether to allow for sharing a direct session remotely. 4280 </desc> 4281 </param> 4282 <param name="sessionType" type="SessionType" dir="return"> 4283 <desc> 4298 <param name="lockType" type="LockType" dir="in"> 4299 <desc> 4300 If set to @c Write, then attempt to acquire an exclusive write lock or fail. 4301 If set to @c Shared, then either acquire an exclusive write lock or establish 4302 a link to an existing session. 4284 4303 </desc> 4285 4304 </param> … … 4312 4331 object which can be used to control machine execution, but it cannot 4313 4332 be used to change all VM settings which would be available after 4314 a <link to="#lock ForSession" /> call.4333 a <link to="#lockMachine" /> call. 4315 4334 4316 4335 As with all <link to="ISession" /> objects, it is recommended to call … … 5924 5943 5925 5944 A console object gets created when a machine has been locked for a 5926 particular session (client process) using <link to="IMachine::lock ForSession" />5945 particular session (client process) using <link to="IMachine::lockMachine" /> 5927 5946 or <link to="IMachine::launchVMProcess"/>. The console object can 5928 5947 then be found in the session's <link to="ISession::console" /> attribute. … … 12755 12774 <ul> 12756 12775 <li>To alter machine settings, one needs to lock a machine for a given session 12757 (client process) by calling <link to="IMachine::lock ForSession"/>. While a12776 (client process) by calling <link to="IMachine::lockMachine"/>. While a 12758 12777 machine is thus locked, no any other process may lock the machine again. 12759 12778 … … 12823 12842 Calling this method is eventually required every time a machine has been 12824 12843 locked for a particular session using the <link to="IMachine::launchVMProcess" /> 12825 or <link to="IMachine::lock ForSession" />) calls. Otherwise the state of12844 or <link to="IMachine::lockMachine" />) calls. Otherwise the state of 12826 12845 the machine will be set to <link to="MachineState_Aborted" /> on the 12827 12846 server, and changes made to the machine settings will be lost. -
trunk/src/VBox/Main/include/MachineImpl.h
r31008 r31019 115 115 struct Session 116 116 { 117 /** Control of the direct session opened by lock ForSession() */117 /** Control of the direct session opened by lockMachine() */ 118 118 ComPtr<IInternalSessionControl> mDirectControl; 119 119 … … 455 455 456 456 // IMachine methods 457 STDMETHOD(Lock ForSession)(ISession *aSession, BOOL fPermitShared, SessionType_T *sessionType);457 STDMETHOD(LockMachine)(ISession *aSession, LockType_T lockType); 458 458 STDMETHOD(LaunchVMProcess)(ISession *aSession, IN_BSTR aType, IN_BSTR aEnvironment, IProgress **aProgress); 459 459 … … 627 627 Utf8Str queryLogFilename(ULONG idx); 628 628 629 HRESULT openSession(IInternalSessionControl *aControl);630 629 HRESULT openRemoteSession(IInternalSessionControl *aControl, 631 630 IN_BSTR aType, IN_BSTR aEnvironment, 632 631 ProgressProxy *aProgress); 633 HRESULT openExistingSession(IInternalSessionControl *aControl);634 632 635 633 HRESULT getDirectControl(ComPtr<IInternalSessionControl> *directControl) -
trunk/src/VBox/Main/testcase/tstVBoxAPILinux.cpp
r31008 r31019 266 266 } 267 267 268 machine->Lock ForSession(session, false /* fPermitShared */, NULL);268 machine->LockMachine(session, LockType_Write); 269 269 if (NS_FAILED(rc)) 270 270 {
Note:
See TracChangeset
for help on using the changeset viewer.