Changeset 24703 in vbox for trunk/src/VBox/Main/ConsoleImpl.cpp
- Timestamp:
- Nov 16, 2009 3:50:47 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/ConsoleImpl.cpp
r24664 r24703 105 105 #include <memory> // for auto_ptr 106 106 #include <vector> 107 #include <typeinfo> 107 108 108 109 … … 1309 1310 } 1310 1311 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 */ 1322 HRESULT 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 1311 1395 #endif /* VBOX_WITH_GUEST_PROPS */ 1312 1396 … … 2704 2788 ///////////////////////////////////////////////////////////////////////////// 2705 2789 2790 /** 2791 * @copydoc VirtualBox::handleUnexpectedExceptions 2792 */ 2793 /* static */ 2794 HRESULT 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 } 2706 2817 2707 2818 /* static */ … … 2750 2861 } 2751 2862 } 2863 2864 // private methods 2865 ///////////////////////////////////////////////////////////////////////////// 2752 2866 2753 2867 /** … … 4876 4990 || mMachineState == MachineState_Restoring 4877 4991 || mMachineState == MachineState_TeleportingPausedVM 4878 || mMachineState == MachineState_TeleportingIn /** @todo Teleportation ???*/4992 || mMachineState == MachineState_TeleportingIn 4879 4993 , ("Invalid machine state: %s\n", Global::stringifyMachineState(mMachineState))); 4880 4994 … … 4894 5008 mVMPoweredOff = true; 4895 5009 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 */ 4901 5019 if ( mMachineState != MachineState_Saving 4902 5020 && mMachineState != MachineState_Restoring … … 4931 5049 aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount ); 4932 5050 4933 #ifdef VBOX_WITH_HGCM4934 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 else4946 rc = doEnumerateGuestProperties(Bstr(""), ComSafeArrayAsOutParam(namesOut),4947 ComSafeArrayAsOutParam(valuesOut),4948 ComSafeArrayAsOutParam(timestampsOut),4949 ComSafeArrayAsOutParam(flagsOut));4950 if (SUCCEEDED(rc))4951 {4952 try4953 {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_Saving4964 || mMachineState == MachineState_LiveSnapshotting4965 )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 might5004 * 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 */5022 5051 5023 5052 /* ---------------------------------------------------------------------- … … 5052 5081 vrc = VINF_SUCCESS; 5053 5082 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 */ 5055 5091 if (!mVMPoweredOff) 5056 5092 { 5057 5093 LogFlowThisFunc(("Powering off the VM...\n")); 5058 5059 /* Leave the lock since EMT will call us back on VMR3PowerOff() */5060 5094 alock.leave(); 5061 5062 5095 vrc = VMR3PowerOff(mpVM); 5063 5064 /* Note that VMR3PowerOff() may fail here (invalid VMSTATE) if the5065 * VM-(guest-)initiated power off happened in parallel a ms before this5066 * call. So far, we let this error pop up on the user's side. */5067 5068 5096 alock.enter(); 5069 5070 5097 } 5071 5098 else 5072 5099 { 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 */ 5074 5103 mVMPoweredOff = false; 5075 5104 } … … 5079 5108 aProgress->SetCurrentOperationProgress(99 * (++ step) / StepCount ); 5080 5109 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 5081 5148 LogFlowThisFunc(("Ready for VM destruction.\n")); 5082 5149 … … 5085 5152 if (RT_SUCCESS(vrc) || autoCaller.state() == InUninit) 5086 5153 { 5087 /* If the machine has an USB co mtroller, release all USB devices5154 /* If the machine has an USB controller, release all USB devices 5088 5155 * (symmetric to the code in captureUSBDevices()) */ 5089 5156 bool fHasUSBController = false;
Note:
See TracChangeset
for help on using the changeset viewer.