VirtualBox

Ignore:
Timestamp:
Nov 16, 2009 3:50:47 PM (15 years ago)
Author:
vboxsync
Message:

Main,GuestProperties: Moved the HGCM shutdown down after we've powered off the VM. Ditto for moving the guest properties to VBoxSVC. Explicitly flush the guest property change notifications before moving them. Added a handleUnexpectedExceptions to Console that is similar to the one found in VirtualBox (i.e. in VBoxSVC).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/ConsoleImpl.cpp

    r24664 r24703  
    105105#include <memory> // for auto_ptr
    106106#include <vector>
     107#include <typeinfo>
    107108
    108109
     
    13091310}
    13101311
     1312/**
     1313 * Helper that is used by powerDown to move the guest properties to VBoxSVC.
     1314 *
     1315 * @param   fSaving         Whether we're saving a machine state and should
     1316 *                          therefore save transient properties as well.
     1317 *
     1318 * @returns COM status code.
     1319 *
     1320 * @remarks This is called without holding the console lock.
     1321 */
     1322HRESULT Console::doMoveGuestPropertiesOnPowerOff(bool fSaving)
     1323{
     1324    /*
     1325     * First, flush any pending notifications.
     1326     */
     1327    VBOXHGCMSVCPARM parm[1];
     1328    parm[0].setUInt32(20*1000/*ms*/);
     1329    int vrc = mVMMDev->hgcmHostCall("VBoxGuestPropSvc", guestProp::FLUSH_NOTIFICATIONS_HOST, 1, &parm[0]);
     1330    if (RT_FAILURE(vrc))
     1331        LogRelFunc(("Flushing notifications failed with rc=%Rrc\n", vrc));
     1332
     1333    /*
     1334     * Enumerate the properties and
     1335     */
     1336    HRESULT                 hrc;
     1337    com::SafeArray<BSTR>    namesOut;
     1338    com::SafeArray<BSTR>    valuesOut;
     1339    com::SafeArray<ULONG64> timestampsOut;
     1340    com::SafeArray<BSTR>    flagsOut;
     1341    try
     1342    {
     1343        Bstr                pattern("");
     1344        hrc = doEnumerateGuestProperties(pattern, ComSafeArrayAsOutParam(namesOut),
     1345                                         ComSafeArrayAsOutParam(valuesOut),
     1346                                         ComSafeArrayAsOutParam(timestampsOut),
     1347                                         ComSafeArrayAsOutParam(flagsOut));
     1348        if (SUCCEEDED(hrc))
     1349        {
     1350            std::vector <BSTR>      names;
     1351            std::vector <BSTR>      values;
     1352            std::vector <ULONG64>   timestamps;
     1353            std::vector <BSTR>      flags;
     1354            for (size_t i = 0; i < namesOut.size(); ++i)
     1355            {
     1356                uint32_t fFlags = guestProp::NILFLAG;
     1357                vrc = guestProp::validateFlags(Utf8Str(flagsOut[i]).raw(), &fFlags); AssertRC(vrc);
     1358                if (   fSaving
     1359                    || !(fFlags & guestProp::TRANSIENT))
     1360                {
     1361                    names.push_back(namesOut[i]);
     1362                    values.push_back(valuesOut[i]);
     1363                    timestamps.push_back(timestampsOut[i]);
     1364                    flags.push_back(flagsOut[i]);
     1365                }
     1366            }
     1367            com::SafeArray<BSTR>    namesIn(names);
     1368            com::SafeArray<BSTR>    valuesIn(values);
     1369            com::SafeArray<ULONG64> timestampsIn(timestamps);
     1370            com::SafeArray<BSTR>    flagsIn(flags);
     1371            if (   namesIn.isNull()
     1372                || valuesIn.isNull()
     1373                || timestampsIn.isNull()
     1374                || flagsIn.isNull()
     1375               )
     1376                throw std::bad_alloc();
     1377            /* PushGuestProperties() calls DiscardSettings(), which calls us back */
     1378            mControl->PushGuestProperties(ComSafeArrayAsInParam(namesIn),
     1379                                          ComSafeArrayAsInParam(valuesIn),
     1380                                          ComSafeArrayAsInParam(timestampsIn),
     1381                                          ComSafeArrayAsInParam(flagsIn));
     1382        }
     1383    }
     1384    catch (...)
     1385    {
     1386        hrc = Console::handleUnexpectedExceptions(RT_SRC_POS);
     1387    }
     1388    if (FAILED(hrc))
     1389        LogRelFunc(("Failed with hrc=%Rhrc\n", hrc));
     1390    return hrc;
     1391}
     1392
     1393
     1394
    13111395#endif /* VBOX_WITH_GUEST_PROPS */
    13121396
     
    27042788/////////////////////////////////////////////////////////////////////////////
    27052789
     2790/**
     2791 * @copydoc VirtualBox::handleUnexpectedExceptions
     2792 */
     2793/* static */
     2794HRESULT Console::handleUnexpectedExceptions(RT_SRC_POS_DECL)
     2795{
     2796    try
     2797    {
     2798        /* re-throw the current exception */
     2799        throw;
     2800    }
     2801    catch (const std::exception &err)
     2802    {
     2803        return setError(E_FAIL, tr("Unexpected exception: %s [%s]\n%s[%d] (%s)"),
     2804                                err.what(), typeid(err).name(),
     2805                                pszFile, iLine, pszFunction);
     2806    }
     2807    catch (...)
     2808    {
     2809        return setError(E_FAIL, tr("Unknown exception\n%s[%d] (%s)"),
     2810                                pszFile, iLine, pszFunction);
     2811    }
     2812
     2813    /* should not get here */
     2814    AssertFailed();
     2815    return E_FAIL;
     2816}
    27062817
    27072818/* static */
     
    27502861    }
    27512862}
     2863
     2864// private methods
     2865/////////////////////////////////////////////////////////////////////////////
    27522866
    27532867/**
     
    48764990              || mMachineState == MachineState_Restoring
    48774991              || mMachineState == MachineState_TeleportingPausedVM
    4878               || mMachineState == MachineState_TeleportingIn         /** @todo Teleportation ???*/
     4992              || mMachineState == MachineState_TeleportingIn
    48794993              , ("Invalid machine state: %s\n", Global::stringifyMachineState(mMachineState)));
    48804994
     
    48945008        mVMPoweredOff = true;
    48955009
    4896     /* go to Stopping state if not already there. Note that we don't go from
    4897      * Saving/Restoring to Stopping because vmstateChangeCallback() needs it to
    4898      * set the state to Saved on VMSTATE_TERMINATED. In terms of protecting from
    4899      * inappropriate operations while leaving the lock below, Saving or
    4900      * Restoring should be fine too.  Ditto for Teleporting* -> Teleported. */
     5010    /*
     5011     * Go to Stopping state if not already there.
     5012     *
     5013     * Note that we don't go from Saving/Restoring to Stopping because
     5014     * vmstateChangeCallback() needs it to set the state to Saved on
     5015     * VMSTATE_TERMINATED. In terms of protecting from inappropriate operations
     5016     * while leaving the lock below, Saving or Restoring should be fine too.
     5017     * Ditto for TeleportingPausedVM -> Teleported.
     5018     */
    49015019    if (   mMachineState != MachineState_Saving
    49025020        && mMachineState != MachineState_Restoring
     
    49315049        aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
    49325050
    4933 #ifdef VBOX_WITH_HGCM
    4934 
    4935 # ifdef VBOX_WITH_GUEST_PROPS  /** @todo r=bird: This may be premature, the VM may still be running at this point! */
    4936 
    4937     /* Save all guest property store entries to the machine XML file */
    4938     com::SafeArray<BSTR> namesOut;
    4939     com::SafeArray<BSTR> valuesOut;
    4940     com::SafeArray<ULONG64> timestampsOut;
    4941     com::SafeArray<BSTR> flagsOut;
    4942     Bstr pattern("");
    4943     if (pattern.isNull()) /** @todo r=bird: What is pattern actually used for?  And, again, what's is the out-of-memory policy in main? */
    4944         rc = E_OUTOFMEMORY;
    4945     else
    4946         rc = doEnumerateGuestProperties(Bstr(""), ComSafeArrayAsOutParam(namesOut),
    4947                                         ComSafeArrayAsOutParam(valuesOut),
    4948                                         ComSafeArrayAsOutParam(timestampsOut),
    4949                                         ComSafeArrayAsOutParam(flagsOut));
    4950     if (SUCCEEDED(rc))
    4951     {
    4952         try
    4953         {
    4954             std::vector <BSTR> names;
    4955             std::vector <BSTR> values;
    4956             std::vector <ULONG64> timestamps;
    4957             std::vector <BSTR> flags;
    4958             for (unsigned i = 0; i < namesOut.size(); ++i)
    4959             {
    4960                 uint32_t fFlags;
    4961                 guestProp::validateFlags(Utf8Str(flagsOut[i]).raw(), &fFlags);
    4962                 if (   !(fFlags & guestProp::TRANSIENT)
    4963                     || mMachineState == MachineState_Saving
    4964                     || mMachineState == MachineState_LiveSnapshotting
    4965                   )
    4966                 {
    4967                     names.push_back(namesOut[i]);
    4968                     values.push_back(valuesOut[i]);
    4969                     timestamps.push_back(timestampsOut[i]);
    4970                     flags.push_back(flagsOut[i]);
    4971                 }
    4972             }
    4973             com::SafeArray<BSTR> namesIn(names);
    4974             com::SafeArray<BSTR> valuesIn(values);
    4975             com::SafeArray<ULONG64> timestampsIn(timestamps);
    4976             com::SafeArray<BSTR> flagsIn(flags);
    4977             if (   namesIn.isNull()
    4978                 || valuesIn.isNull()
    4979                 || timestampsIn.isNull()
    4980                 || flagsIn.isNull()
    4981                 )
    4982                 throw std::bad_alloc();
    4983             /* PushGuestProperties() calls DiscardSettings(), which calls us back */
    4984             alock.leave();
    4985             mControl->PushGuestProperties(ComSafeArrayAsInParam(namesIn),
    4986                                           ComSafeArrayAsInParam(valuesIn),
    4987                                           ComSafeArrayAsInParam(timestampsIn),
    4988                                           ComSafeArrayAsInParam(flagsIn));
    4989             alock.enter();
    4990         }
    4991         catch (std::bad_alloc)
    4992         {
    4993             rc = E_OUTOFMEMORY;
    4994         }
    4995     }
    4996 
    4997     /* advance percent count */
    4998     if (aProgress)
    4999         aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
    5000 
    5001 # endif /* VBOX_WITH_GUEST_PROPS defined */
    5002 
    5003     /* Shutdown HGCM services before stopping the guest, because they might
    5004      * need a cleanup. */
    5005     if (mVMMDev)
    5006     {
    5007         LogFlowThisFunc(("Shutdown HGCM...\n"));
    5008 
    5009         /* Leave the lock since EMT will call us back as addVMCaller() */
    5010         alock.leave();
    5011 
    5012         mVMMDev->hgcmShutdown();
    5013 
    5014         alock.enter();
    5015     }
    5016 
    5017     /* advance percent count */
    5018     if (aProgress)
    5019         aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
    5020 
    5021 #endif /* VBOX_WITH_HGCM */
    50225051
    50235052    /* ----------------------------------------------------------------------
     
    50525081    vrc = VINF_SUCCESS;
    50535082
    5054     /* Power off the VM if not already done that */
     5083    /*
     5084     * Power off the VM if not already done that.
     5085     * Leave the lock since EMT will call vmstateChangeCallback.
     5086     *
     5087     * Note that VMR3PowerOff() may fail here (invalid VMSTATE) if the
     5088     * VM-(guest-)initiated power off happened in parallel a ms before this
     5089     * call. So far, we let this error pop up on the user's side.
     5090     */
    50555091    if (!mVMPoweredOff)
    50565092    {
    50575093        LogFlowThisFunc(("Powering off the VM...\n"));
    5058 
    5059         /* Leave the lock since EMT will call us back on VMR3PowerOff() */
    50605094        alock.leave();
    5061 
    50625095        vrc = VMR3PowerOff(mpVM);
    5063 
    5064         /* Note that VMR3PowerOff() may fail here (invalid VMSTATE) if the
    5065          * VM-(guest-)initiated power off happened in parallel a ms before this
    5066          * call. So far, we let this error pop up on the user's side. */
    5067 
    50685096        alock.enter();
    5069 
    50705097    }
    50715098    else
    50725099    {
    5073         /* reset the flag for further re-use */
     5100        /** @todo r=bird: Doesn't make sense. Please remove after 3.1 has been branched
     5101         *        off. */
     5102        /* reset the flag for future re-use */
    50745103        mVMPoweredOff = false;
    50755104    }
     
    50795108        aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
    50805109
     5110#ifdef VBOX_WITH_HGCM
     5111# ifdef VBOX_WITH_GUEST_PROPS
     5112    /*
     5113     * Save all guest property store entries to the machine XML file
     5114     * and hand controll over to VBoxSVC.  Ignoring failure for now.
     5115     */
     5116    LogFlowThisFunc(("Moving Guest Properties to XML/VBoxSVC...\n"));
     5117    bool fIsSaving = mMachineState == MachineState_Saving
     5118                  || mMachineState == MachineState_LiveSnapshotting;
     5119    alock.leave();
     5120    doMoveGuestPropertiesOnPowerOff(fIsSaving);
     5121    alock.enter();
     5122
     5123    /* advance percent count */
     5124    if (aProgress)
     5125        aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
     5126
     5127# endif /* VBOX_WITH_GUEST_PROPS defined */
     5128
     5129    /* Shutdown HGCM services before destroying the VM. */
     5130    if (mVMMDev)
     5131    {
     5132        LogFlowThisFunc(("Shutdown HGCM...\n"));
     5133
     5134        /* Leave the lock since EMT will call us back as addVMCaller() */
     5135        alock.leave();
     5136
     5137        mVMMDev->hgcmShutdown();
     5138
     5139        alock.enter();
     5140    }
     5141
     5142    /* advance percent count */
     5143    if (aProgress)
     5144        aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount );
     5145
     5146#endif /* VBOX_WITH_HGCM */
     5147
    50815148    LogFlowThisFunc(("Ready for VM destruction.\n"));
    50825149
     
    50855152    if (RT_SUCCESS(vrc) || autoCaller.state() == InUninit)
    50865153    {
    5087         /* If the machine has an USB comtroller, release all USB devices
     5154        /* If the machine has an USB controller, release all USB devices
    50885155         * (symmetric to the code in captureUSBDevices()) */
    50895156        bool fHasUSBController = false;
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