VirtualBox

Changeset 34839 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 8, 2010 3:32:32 PM (14 years ago)
Author:
vboxsync
Message:

Frontends/VBoxHeadless: use VirtualBoxClient object, and terminate VM as cleanly as possible if VBoxSVC becomes unavailable

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp

    r34122 r34839  
    7676
    7777/* global weak references (for event handlers) */
    78 static ISession *gSession = NULL;
    7978static IConsole *gConsole = NULL;
    8079static EventQueue *gEventQ = NULL;
     
    8887
    8988////////////////////////////////////////////////////////////////////////////////
     89
     90/**
     91 *  Handler for VirtualBoxClient events.
     92 */
     93class VirtualBoxClientEventListener
     94{
     95public:
     96    VirtualBoxClientEventListener()
     97    {
     98    }
     99
     100    virtual ~VirtualBoxClientEventListener()
     101    {
     102    }
     103
     104    STDMETHOD(HandleEvent)(VBoxEventType_T aType, IEvent * aEvent)
     105    {
     106        switch (aType)
     107        {
     108            case VBoxEventType_OnVBoxSVCUnavailable:
     109            {
     110                ComPtr<IVBoxSVCUnavailableEvent> pVSUEv = aEvent;
     111                Assert(pVSUEv);
     112
     113                LogRel(("VBoxHeadless: VBoxSVC became unavailable, exiting.\n"));
     114                RTPrintf("VBoxSVC became unavailable, exiting.\n");
     115                /* Terminate the VM as cleanly as possible given that VBoxSVC
     116                 * is no longer present. */
     117                g_fTerminateFE = true;
     118                gEventQ->interruptEventQueueProcessing();
     119                break;
     120            }
     121            default:
     122                AssertFailed();
     123        }
     124
     125        return S_OK;
     126    }
     127
     128private:
     129};
    90130
    91131/**
     
    201241{
    202242public:
    203     ConsoleEventListener()
    204     {
    205         mLastVRDEPort = -1;
     243    ConsoleEventListener() :
     244        mLastVRDEPort(-1),
     245        m_fIgnorePowerOffEvents(false)
     246    {
    206247    }
    207248
     
    249290                /* Terminate any event wait operation if the machine has been
    250291                 * PoweredDown/Saved/Aborted. */
    251                 if (machineState < MachineState_Running)
     292                if (machineState < MachineState_Running && !m_fIgnorePowerOffEvents)
    252293                {
    253294                    g_fTerminateFE = true;
     
    305346    }
    306347
     348    void ignorePowerOffEvents(bool fIgnore)
     349    {
     350        m_fIgnorePowerOffEvents = fIgnore;
     351    }
     352
    307353private:
    308354
    309355    long mLastVRDEPort;
     356    bool m_fIgnorePowerOffEvents;
    310357};
    311358
     359typedef ListenerImpl<VirtualBoxClientEventListener> VirtualBoxClientEventListenerImpl;
    312360typedef ListenerImpl<VirtualBoxEventListener> VirtualBoxEventListenerImpl;
    313361typedef ListenerImpl<ConsoleEventListener> ConsoleEventListenerImpl;
    314362
     363VBOX_LISTENER_DECLARE(VirtualBoxClientEventListenerImpl)
    315364VBOX_LISTENER_DECLARE(VirtualBoxEventListenerImpl)
    316365VBOX_LISTENER_DECLARE(ConsoleEventListenerImpl)
     
    705754    }
    706755
     756    ComPtr<IVirtualBoxClient> pVirtualBoxClient;
    707757    ComPtr<IVirtualBox> virtualBox;
    708758    ComPtr<ISession> session;
     759    ComPtr<IMachine> machine;
    709760    bool fSessionOpened = false;
    710     IEventListener *vboxListener = NULL, *consoleListener = NULL;
     761    IEventListener *vboxClientListener = NULL;
     762    IEventListener *vboxListener = NULL;
     763    ConsoleEventListenerImpl *consoleListener = NULL;
    711764
    712765    do
    713766    {
    714         rc = virtualBox.createLocalObject(CLSID_VirtualBox);
     767        rc = pVirtualBoxClient.createInprocObject(CLSID_VirtualBoxClient);
    715768        if (FAILED(rc))
    716             RTPrintf("VBoxHeadless: ERROR: failed to create the VirtualBox object!\n");
    717         else
    718         {
    719             rc = session.createInprocObject(CLSID_Session);
    720             if (FAILED(rc))
    721                 RTPrintf("VBoxHeadless: ERROR: failed to create a session object!\n");
    722         }
    723 
    724         if (FAILED(rc))
    725         {
     769        {
     770            RTPrintf("VBoxHeadless: ERROR: failed to create the VirtualBoxClient object!\n");
    726771            com::ErrorInfo info;
    727772            if (!info.isFullAvailable() && !info.isBasicAvailable())
     
    732777            else
    733778                GluePrintErrorInfo(info);
     779            break;
     780        }
     781
     782        rc = pVirtualBoxClient->COMGETTER(VirtualBox)(virtualBox.asOutParam());
     783        if (FAILED(rc))
     784        {
     785            RTPrintf("Failed to get VirtualBox object (rc=%Rhrc)!\n", rc);
     786            break;
     787        }
     788        rc = pVirtualBoxClient->COMGETTER(Session)(session.asOutParam());
     789        if (FAILED(rc))
     790        {
     791            RTPrintf("Failed to get session object (rc=%Rhrc)!\n", rc);
    734792            break;
    735793        }
     
    761819
    762820        /* get the mutable machine */
    763         ComPtr<IMachine> machine;
    764821        CHECK_ERROR_BREAK(console, COMGETTER(Machine)(machine.asOutParam()));
    765822
     
    930987
    931988        /* initialize global references */
    932         gSession = session;
    933989        gConsole = console;
    934990        gEventQ = com::EventQueue::getMainEventQueue();
     991
     992        /* VirtualBoxClient events registration. */
     993        {
     994            ComPtr<IEventSource> pES;
     995            CHECK_ERROR(pVirtualBoxClient, COMGETTER(EventSource)(pES.asOutParam()));
     996            vboxClientListener = new VirtualBoxClientEventListenerImpl();
     997            com::SafeArray <VBoxEventType_T> eventTypes;
     998            eventTypes.push_back(VBoxEventType_OnVBoxSVCUnavailable);
     999            CHECK_ERROR(pES, RegisterListener(vboxClientListener, ComSafeArrayAsInParam(eventTypes), true));
     1000        }
    9351001
    9361002        /* Console events registration. */
     
    11251191    while (0);
    11261192
     1193    /*
     1194     * Get the machine state.
     1195     */
     1196    MachineState_T machineState = MachineState_Aborted;
     1197    if (!machine.isNull())
     1198        machine->COMGETTER(State)(&machineState);
     1199
     1200    /*
     1201     * Turn off the VM if it's running
     1202     */
     1203    if (   gConsole
     1204        && (   machineState == MachineState_Running
     1205            || machineState == MachineState_Teleporting
     1206            || machineState == MachineState_LiveSnapshotting
     1207            /** @todo power off paused VMs too? */
     1208           )
     1209       )
     1210    do
     1211    {
     1212        consoleListener->getWrapped()->ignorePowerOffEvents(true);
     1213        ComPtr<IProgress> pProgress;
     1214        CHECK_ERROR_BREAK(gConsole, PowerDown(pProgress.asOutParam()));
     1215        CHECK_ERROR_BREAK(pProgress, WaitForCompletion(-1));
     1216        BOOL completed;
     1217        CHECK_ERROR_BREAK(pProgress, COMGETTER(Completed)(&completed));
     1218        ASSERT(completed);
     1219        LONG hrc;
     1220        CHECK_ERROR_BREAK(pProgress, COMGETTER(ResultCode)(&hrc));
     1221        if (FAILED(hrc))
     1222        {
     1223            RTPrintf("VBoxHeadless: ERROR: Failed to power down VM!");
     1224            com::ErrorInfo info;
     1225            if (!info.isFullAvailable() && !info.isBasicAvailable())
     1226                com::GluePrintRCMessage(hrc);
     1227            else
     1228                GluePrintErrorInfo(info);
     1229            break;
     1230        }
     1231    } while (0);
     1232
    11271233    /* VirtualBox callback unregistration. */
    11281234    if (vboxListener)
     
    11301236        ComPtr<IEventSource> es;
    11311237        CHECK_ERROR(virtualBox, COMGETTER(EventSource)(es.asOutParam()));
    1132         CHECK_ERROR(es, UnregisterListener(vboxListener));
     1238        if (!es.isNull())
     1239            CHECK_ERROR(es, UnregisterListener(vboxListener));
    11331240        vboxListener->Release();
    11341241    }
     
    11391246        ComPtr<IEventSource> es;
    11401247        CHECK_ERROR(gConsole, COMGETTER(EventSource)(es.asOutParam()));
    1141         CHECK_ERROR(es, UnregisterListener(consoleListener));
     1248        if (!es.isNull())
     1249            CHECK_ERROR(es, UnregisterListener(consoleListener));
    11421250        consoleListener->Release();
     1251    }
     1252
     1253    /* VirtualBoxClient callback unregistration. */
     1254    if (consoleListener)
     1255    {
     1256        ComPtr<IEventSource> pES;
     1257        CHECK_ERROR(pVirtualBoxClient, COMGETTER(EventSource)(pES.asOutParam()));
     1258        if (!pES.isNull())
     1259            CHECK_ERROR(pES, UnregisterListener(vboxClientListener));
     1260        vboxClientListener->Release();
    11431261    }
    11441262
     
    11591277    session.setNull();
    11601278    virtualBox.setNull();
     1279    pVirtualBoxClient.setNull();
    11611280
    11621281    com::Shutdown();
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