VirtualBox

Changeset 36673 in vbox for trunk/src/VBox/Main/src-server


Ignore:
Timestamp:
Apr 14, 2011 3:22:37 PM (14 years ago)
Author:
vboxsync
Message:

Main/Machine: add a way to terminate VM processes if they don't respond to the usual requests. Not an API change, just a comment change, and a slight VBoxManage touch up so that one can trigger it.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/MachineImpl.cpp

    r36664 r36673  
    30443044            // this machine is awaiting for a spawning session to be opened:
    30453045            // then the calling process must be the one that got started by
    3046             // launchVMProcess()
     3046            // LaunchVMProcess()
    30473047
    30483048            LogFlowThisFunc(("mSession.mPid=%d(0x%x)\n", mData->mSession.mPid, mData->mSession.mPid));
     
    30523052                return setError(E_ACCESSDENIED,
    30533053                                tr("An unexpected process (PID=0x%08X) has tried to lock the "
    3054                                    "machine '%s', while only the process started by launchVMProcess (PID=0x%08X) is allowed"),
     3054                                   "machine '%s', while only the process started by LaunchVMProcess (PID=0x%08X) is allowed"),
    30553055                                pid, mUserData->s.strName.c_str(), mData->mSession.mPid);
    30563056        }
     
    30813081             *  Leave the lock before calling the client process -- it will call
    30823082             *  Machine/SessionMachine methods. Leaving the lock here is quite safe
    3083              *  because the state is Spawning, so that openRemotesession() and
    3084              *  openExistingSession() calls will fail. This method, called before we
     3083             *  because the state is Spawning, so that LaunchVMProcess() and
     3084             *  LockMachine() calls will fail. This method, called before we
    30853085             *  enter the lock again, will fail because of the wrong PID.
    30863086             *
     
    31203120                {
    31213121                    /*
    3122                      *  after openRemoteSession(), the first and the only
     3122                     *  after LaunchVMProcess(), the first and the only
    31233123                     *  entry in remoteControls is that remote session
    31243124                     */
     
    32273227                                      IProgress **aProgress)
    32283228{
    3229     CheckComArgNotNull(aSession);
     3229    Utf8Str strType(aType);
     3230    Utf8Str strEnvironment(aEnvironment);
     3231
     3232    /* "emergencystop" doesn't need the session, so skip the checks/interface
     3233     * retrieval. This code doesn't quite fit in here, but introducing a
     3234     * special API method would be even more effort, and would require explicit
     3235     * support by every API client. It's better to hide the feature a bit. */
     3236    if (strType != "emergencystop")
     3237        CheckComArgNotNull(aSession);
    32303238    CheckComArgStrNotEmptyOrNull(aType);
    32313239    CheckComArgOutPointerValid(aProgress);
     
    32343242    if (FAILED(autoCaller.rc())) return autoCaller.rc();
    32353243
    3236     /* check the session state */
    3237     SessionState_T state;
    3238     HRESULT rc = aSession->COMGETTER(State)(&state);
    3239     if (FAILED(rc)) return rc;
    3240 
    3241     if (state != SessionState_Unlocked)
    3242         return setError(VBOX_E_INVALID_OBJECT_STATE,
    3243                         tr("The given session is busy"));
    3244 
    3245     /* get the IInternalSessionControl interface */
    3246     ComPtr<IInternalSessionControl> control = aSession;
    3247     ComAssertMsgRet(!!control, ("No IInternalSessionControl interface"),
    3248                       E_INVALIDARG);
     3244    ComPtr<IInternalSessionControl> control;
     3245    HRESULT rc = S_OK;
     3246
     3247    if (strType != "emergencystop")
     3248    {
     3249        /* check the session state */
     3250        SessionState_T state;
     3251        rc = aSession->COMGETTER(State)(&state);
     3252        if (FAILED(rc))
     3253            return rc;
     3254
     3255        if (state != SessionState_Unlocked)
     3256            return setError(VBOX_E_INVALID_OBJECT_STATE,
     3257                            tr("The given session is busy"));
     3258
     3259        /* get the IInternalSessionControl interface */
     3260        control = aSession;
     3261        ComAssertMsgRet(!control.isNull(),
     3262                        ("No IInternalSessionControl interface"),
     3263                        E_INVALIDARG);
     3264    }
    32493265
    32503266    /* get the teleporter enable state for the progress object init. */
     
    32553271
    32563272    /* create a progress object */
    3257     ComObjPtr<ProgressProxy> progress;
    3258     progress.createObject();
    3259     rc = progress->init(mParent,
    3260                         static_cast<IMachine*>(this),
    3261                         Bstr(tr("Spawning session")).raw(),
    3262                         TRUE /* aCancelable */,
    3263                         fTeleporterEnabled ? 20 : 10 /* uTotalOperationsWeight */,
    3264                         Bstr(tr("Spawning session")).raw(),
    3265                         2 /* uFirstOperationWeight */,
    3266                         fTeleporterEnabled ? 3 : 1 /* cOtherProgressObjectOperations */);
    3267     if (SUCCEEDED(rc))
    3268     {
    3269         rc = openRemoteSession(control, aType, aEnvironment, progress);
     3273    if (strType != "emergencystop")
     3274    {
     3275        ComObjPtr<ProgressProxy> progress;
     3276        progress.createObject();
     3277        rc = progress->init(mParent,
     3278                            static_cast<IMachine*>(this),
     3279                            BstrFmt(tr("Starting VM \"%s\" (%s)"), aType).raw(),
     3280                            TRUE /* aCancelable */,
     3281                            fTeleporterEnabled ? 20 : 10 /* uTotalOperationsWeight */,
     3282                            Bstr(tr("Spawning session")).raw(),
     3283                            2 /* uFirstOperationWeight */,
     3284                            fTeleporterEnabled ? 3 : 1 /* cOtherProgressObjectOperations */);
     3285
    32703286        if (SUCCEEDED(rc))
    32713287        {
    3272             progress.queryInterfaceTo(aProgress);
    3273 
    3274             /* signal the client watcher thread */
    3275             mParent->updateClientWatcher();
    3276 
    3277             /* fire an event */
    3278             mParent->onSessionStateChange(getId(), SessionState_Spawning);
    3279         }
     3288            rc = launchVMProcess(control, strType, strEnvironment, progress);
     3289            if (SUCCEEDED(rc))
     3290            {
     3291                progress.queryInterfaceTo(aProgress);
     3292
     3293                /* signal the client watcher thread */
     3294                mParent->updateClientWatcher();
     3295
     3296                /* fire an event */
     3297                mParent->onSessionStateChange(getId(), SessionState_Spawning);
     3298            }
     3299        }
     3300    }
     3301    else
     3302    {
     3303        /* no progress object - either instant success or failure */
     3304        *aProgress = NULL;
     3305
     3306        AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     3307
     3308        if (mData->mSession.mState != SessionState_Locked)
     3309            return setError(VBOX_E_INVALID_OBJECT_STATE,
     3310                            tr("The machine '%s' is not locked by a session"),
     3311                            mUserData->s.strName.c_str());
     3312
     3313        /* must have a VM process associated - do not kill normal API clients
     3314         * with an open session */
     3315        if (!Global::IsOnline(mData->mMachineState))
     3316            return setError(VBOX_E_INVALID_OBJECT_STATE,
     3317                            tr("The machine '%s' does not have a VM process"),
     3318                            mUserData->s.strName.c_str());
     3319
     3320        /* forcibly terminate the VM process */
     3321        if (mData->mSession.mPid != NIL_RTPROCESS)
     3322            RTProcTerminate(mData->mSession.mPid);
     3323
     3324        /* signal the client watcher thread, as most likely the client has
     3325         * been terminated */
     3326        mParent->updateClientWatcher();
    32803327    }
    32813328
     
    59475994        fireHostPciDevicePlugEvent(es, mid.raw(), false /* unplugged */, true /* success */, pAttach, NULL);
    59485995    }
    5949    
     5996
    59505997    return fRemoved ? S_OK : setError(VBOX_E_OBJECT_NOT_FOUND,
    59515998                                      tr("No host PCI device %08x attached"),
     
    61696216 *        (inside the lock).
    61706217 */
    6171 HRESULT Machine::openRemoteSession(IInternalSessionControl *aControl,
    6172                                    IN_BSTR aType,
    6173                                    IN_BSTR aEnvironment,
    6174                                    ProgressProxy *aProgress)
     6218HRESULT Machine::launchVMProcess(IInternalSessionControl *aControl,
     6219                                 const Utf8Str &strType,
     6220                                 const Utf8Str &strEnvironment,
     6221                                 ProgressProxy *aProgress)
    61756222{
    61766223    LogFlowThisFuncEnter();
     
    62156262    RTENV env = RTENV_DEFAULT;
    62166263
    6217     if (aEnvironment != NULL && *aEnvironment)
     6264    if (!strEnvironment.isEmpty())
    62186265    {
    62196266        char *newEnvStr = NULL;
     
    62256272            AssertRCBreakStmt(vrc2, vrc = vrc2);
    62266273
    6227             newEnvStr = RTStrDup(Utf8Str(aEnvironment).c_str());
     6274            newEnvStr = RTStrDup(strEnvironment.c_str());
    62286275            AssertPtrBreakStmt(newEnvStr, vrc = vrc2);
    62296276
     
    62636310            RTStrFree(newEnvStr);
    62646311    }
    6265 
    6266     Utf8Str strType(aType);
    62676312
    62686313    /* Qt is default */
     
    1056910614    {
    1057010615        /* mType is not null when this machine's process has been started by
    10571          * Machine::launchVMProcess(), therefore it is our child.  We
     10616         * Machine::LaunchVMProcess(), therefore it is our child.  We
    1057210617         * need to queue the PID to reap the process (and avoid zombies on
    1057310618         * Linux). */
     
    1079310838        return VBOX_E_INVALID_OBJECT_STATE;
    1079410839
    10795     /* Finalize the openRemoteSession progress object. */
     10840    /* Finalize the LaunchVMProcess progress object. */
    1079610841    if (mData->mSession.mProgress)
    1079710842    {
     
    1109611141         * it releases the IPC semaphore.
    1109711142         * Note! Because we're "reusing" mProgress here, this must be a proxy
    11098          *       object just like for openRemoteSession. */
     11143         *       object just like for LaunchVMProcess. */
    1109911144        Assert(mData->mSession.mProgress.isNull());
    1110011145        ComObjPtr<ProgressProxy> progress;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette