third_party/virtualbox/src/VBox/Main/src-server/MachineImpl.cpp
/**
 *  @note Locks this object for writing.
 */
@note Locks this object for writing.
@note Locks this object for writing .
HRESULT SessionMachine::onSessionEnd(const ComPtr<ISession> &aSession,
                                     ComPtr<IProgress> &aProgress)
{
    LogFlowThisFuncEnter();
    LogFlowThisFunc(("callerstate=%d\n", getObjectState().getState()));
    ComPtr<IInternalSessionControl> control(aSession);
    ComAssertRet(!control.isNull(), E_INVALIDARG);
    AutoMultiWriteLock2 alock(mParent, this COMMA_LOCKVAL_SRC_POS);
    if (control == mData->mSession.mDirectControl)
    {
        Assert(mData->mSession.mState == SessionState_Locked);
        mData->mSession.mState = SessionState_Unlocking;
        mData->mSession.mDirectControl.setNull();
        LogFlowThisFunc(("Direct control is set to NULL\n"));
        if (mData->mSession.mProgress)
        {
            mData->mSession.mProgress->notifyComplete(E_FAIL,
                                                      COM_IIDOF(ISession),
                                                      getComponentName(),
                                                      tr("The VM session was closed before any attempt to power it on"));
            mData->mSession.mProgress.setNull();
        }
        Assert(mData->mSession.mProgress.isNull());
        ComObjPtr<ProgressProxy> progress;
        progress.createObject();
        ComPtr<IUnknown> pPeer(mPeer);
        progress->init(mParent, pPeer,
                       Bstr(tr("Closing session")).raw(),
                       FALSE );
        progress.queryInterfaceTo(aProgress.asOutParam());
        mData->mSession.mProgress = progress;
    }
    else
    {
        bool found = false;
        for (Data::Session::RemoteControlList::iterator
             it = mData->mSession.mRemoteControls.begin();
             it != mData->mSession.mRemoteControls.end();
             ++it)
        {
            if (control == *it)
            {
                found = true;
                mData->mSession.mRemoteControls.erase(it);
                break;
            }
        }
        ComAssertMsgRet(found, ("The session is not found in the session list!"),
                         E_INVALIDARG);
    }
    mParent->i_updateClientWatcher();
    LogFlowThisFuncLeave();
    return S_OK;
}
HRESULT SessionMachine :: onSessionEnd ( const ComPtr < ISession > & aSession , ComPtr < IProgress > & aProgress ) { LogFlowThisFuncEnter ( ) ; LogFlowThisFunc ( ( " \n " , getObjectState ( ) . getState ( ) ) ) ; ComPtr < IInternalSessionControl > control ( aSession ) ; ComAssertRet ( ! control . isNull ( ) , E_INVALIDARG ) ; AutoMultiWriteLock2 alock ( mParent , this COMMA_LOCKVAL_SRC_POS ) ; if ( control == mData -> mSession . mDirectControl ) { Assert ( mData -> mSession . mState == SessionState_Locked ) ; mData -> mSession . mState = SessionState_Unlocking ; mData -> mSession . mDirectControl . setNull ( ) ; LogFlowThisFunc ( ( " \n " ) ) ; if ( mData -> mSession . mProgress ) { mData -> mSession . mProgress -> notifyComplete ( E_FAIL , COM_IIDOF ( ISession ) , getComponentName ( ) , tr ( " " ) ) ; mData -> mSession . mProgress . setNull ( ) ; } Assert ( mData -> mSession . mProgress . isNull ( ) ) ; ComObjPtr < ProgressProxy > progress ; progress . createObject ( ) ; ComPtr < IUnknown > pPeer ( mPeer ) ; progress -> init ( mParent , pPeer , Bstr ( tr ( " " ) ) . raw ( ) , FALSE ) ; progress . queryInterfaceTo ( aProgress . asOutParam ( ) ) ; mData -> mSession . mProgress = progress ; } else { bool found = false ; for ( Data :: Session :: RemoteControlList :: iterator it = mData -> mSession . mRemoteControls . begin ( ) ; it != mData -> mSession . mRemoteControls . end ( ) ; ++ it ) { if ( control == * it ) { found = true ; mData -> mSession . mRemoteControls . erase ( it ) ; break ; } } ComAssertMsgRet ( found , ( " " ) , E_INVALIDARG ) ; } mParent -> i_updateClientWatcher ( ) ; LogFlowThisFuncLeave ( ) ; return S_OK ; }
@note Locks this object for writing.
@note Locks this object for writing .
/*
     *  We don't assert below because it might happen that a non-direct session
     *  informs us it is closed right after we've been uninitialized -- it's ok.
     */ /* get IInternalSessionControl interface */ /* Creating a Progress object requires the VirtualBox lock, and
     * thus locking it here is required by the lock order rules. */ /* The direct session is being normally closed by the client process
         * ----------------------------------------------------------------- */ /* go to the closing state (essential for all open*Session() calls and
         * for #i_checkForDeath()) */ /* set direct control to NULL to release the remote instance */ /* finalize the progress, someone might wait if a frontend
             * closes the session before powering on the VM. */ /* Create the progress object the client will use to wait until
         * #i_checkForDeath() is called to uninitialize this session object after
         * it releases the IPC semaphore.
         * Note! Because we're "reusing" mProgress here, this must be a proxy
         *       object just like for LaunchVMProcess. */ /* aCancelable */ /* the remote session is being normally closed */ // This MUST be erase(it), not remove(*it) as the latter // triggers a very nasty use after free due to the place where // the value "lives". /* signal the client watcher thread, because the client is going away */