Changeset 46720 in vbox
- Timestamp:
- Jun 21, 2013 10:07:31 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/manual/user_ChangeLogImpl.xml
r46524 r46720 27 27 <para>Settings: global and per-VM default frontend configuration, 28 28 useful to select the use of alternative VM frontends</para> 29 </listitem> 30 31 <listitem> 32 <para>Settings: limit depth of snapshot tree to 250 levels, as more 33 will lead to decreased performance and may trigger crashes</para> 29 34 </listitem> 30 35 -
trunk/include/VBox/settings.h
r46667 r46720 50 50 #include <list> 51 51 #include <map> 52 53 /** 54 * Maximum depth of the snapshot tree, to prevent stack overflows. 55 * XPCOM has a relatively low stack size for its workers, and we have 56 * to avoid crashes due to exceeding the limit both on reading and 57 * writing config files. 58 */ 59 #define SETTINGS_SNAPSHOT_DEPTH_MAX 250 52 60 53 61 namespace xml … … 1196 1204 void readAutostart(const xml::ElementNode *pElmAutostart, Autostart *pAutostart); 1197 1205 void readGroups(const xml::ElementNode *elmGroups, StringsList *pllGroups); 1198 void readSnapshot( const xml::ElementNode &elmSnapshot, Snapshot &snap);1206 void readSnapshot(uint32_t depth, const xml::ElementNode &elmSnapshot, Snapshot &snap); 1199 1207 void convertOldOSType_pre1_5(com::Utf8Str &str); 1200 1208 void readMachine(const xml::ElementNode &elmMachine); … … 1209 1217 void buildAutostartXML(xml::ElementNode *pElmParent, const Autostart *pAutostart); 1210 1218 void buildGroupsXML(xml::ElementNode *pElmParent, const StringsList *pllGroups); 1211 void buildSnapshotXML( xml::ElementNode &elmParent, const Snapshot &snap);1219 void buildSnapshotXML(uint32_t depth, xml::ElementNode &elmParent, const Snapshot &snap); 1212 1220 1213 1221 void bumpSettingsVersionIfNeeded(); -
trunk/src/VBox/Main/include/SnapshotImpl.h
r42887 r46720 101 101 const Utf8Str& getStateFilePath() const; 102 102 103 uint32_t getDepth(); 104 103 105 ULONG getChildrenCount(); 104 106 ULONG getAllChildrenCount(); -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r45597 r46720 3426 3426 } 3427 3427 3428 /* Save the error information now, the implicit restore when this goes 3429 * out of scope will throw away spurious additional errors created below. */ 3430 ErrorInfoKeeper eik; 3428 3431 for (GuidList::const_iterator it = llRegistryIDs.begin(); 3429 3432 it != llRegistryIDs.end(); -
trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
r45367 r46720 496 496 497 497 /** 498 * Returns the depth in the snapshot tree for this snapshot. 499 * 500 * @note takes the snapshot tree lock 501 */ 502 503 uint32_t Snapshot::getDepth() 504 { 505 AutoCaller autoCaller(this); 506 AssertComRC(autoCaller.rc()); 507 508 // snapshots tree is protected by machine lock 509 AutoReadLock alock(m->pMachine COMMA_LOCKVAL_SRC_POS); 510 511 uint32_t cDepth = 0; 512 ComObjPtr<Snapshot> pSnap(this); 513 while (!pSnap.isNull()) 514 { 515 pSnap = pSnap->m->pParent; 516 cDepth++; 517 } 518 519 return cDepth; 520 } 521 522 /** 498 523 * Returns the number of direct child snapshots, without grandchildren. 499 524 * Does not recurse. … … 791 816 ++it) 792 817 { 793 settings::Snapshot snap; 794 rc = (*it)->saveSnapshotImpl(snap, aAttrsOnly); 795 if (FAILED(rc)) return rc; 796 797 data.llChildSnapshots.push_back(snap); 818 // Use the heap to reduce the stack footprint. Each recursion needs 819 // over 1K, and there can be VMs with deeply nested snapshots. The 820 // stack can be quite small, especially with XPCOM. 821 822 settings::Snapshot *snap = new settings::Snapshot(); 823 rc = (*it)->saveSnapshotImpl(*snap, aAttrsOnly); 824 if (FAILED(rc)) 825 { 826 delete snap; 827 return rc; 828 } 829 data.llChildSnapshots.push_back(*snap); 830 delete snap; 798 831 } 799 832 } … … 1420 1453 AssertReturn(mConsoleTaskData.mLastState == MachineState_Null, E_FAIL); 1421 1454 AssertReturn(mConsoleTaskData.mSnapshot.isNull(), E_FAIL); 1455 1456 if ( mData->mCurrentSnapshot 1457 && mData->mCurrentSnapshot->getDepth() >= SETTINGS_SNAPSHOT_DEPTH_MAX) 1458 { 1459 return setError(VBOX_E_INVALID_OBJECT_STATE, 1460 tr("Cannot take another snapshot for machine '%s', because it exceeds the maximum snapshot depth limit. Please delete some earlier snapshot which you no longer need"), 1461 mUserData->s.strName.c_str()); 1462 } 1422 1463 1423 1464 if ( !fTakingSnapshotOnline … … 2108 2149 if (childrenCount > 1) 2109 2150 return setError(VBOX_E_INVALID_OBJECT_STATE, 2110 tr("Snapshot '%s' of the machine '%s' cannot be deleted .because it has %d child snapshots, which is more than the one snapshot allowed for deletion"),2151 tr("Snapshot '%s' of the machine '%s' cannot be deleted, because it has %d child snapshots, which is more than the one snapshot allowed for deletion"), 2111 2152 pSnapshot->getName().c_str(), 2112 2153 mUserData->s.strName.c_str(), -
trunk/src/VBox/Main/xml/Settings.cpp
r46667 r46720 3479 3479 * Snapshot structure. 3480 3480 * 3481 * @param depth 3481 3482 * @param elmSnapshot 3482 3483 * @param snap 3483 3484 */ 3484 void MachineConfigFile::readSnapshot(const xml::ElementNode &elmSnapshot, 3485 void MachineConfigFile::readSnapshot(uint32_t depth, 3486 const xml::ElementNode &elmSnapshot, 3485 3487 Snapshot &snap) 3486 3488 { 3489 if (depth > SETTINGS_SNAPSHOT_DEPTH_MAX) 3490 throw ConfigFileError(this, &elmSnapshot, N_("Maximum snapshot tree depth of %u exceeded"), depth); 3491 3487 3492 Utf8Str strTemp; 3488 3493 … … 3531 3536 if (pelmChildSnapshot->nameEquals("Snapshot")) 3532 3537 { 3533 Snapshot child; 3534 readSnapshot(*pelmChildSnapshot, child); 3535 snap.llChildSnapshots.push_back(child); 3538 // Use the heap to reduce the stack footprint. Each 3539 // recursion needs over 1K, and there can be VMs with 3540 // deeply nested snapshots. The stack can be quite 3541 // small, especially with XPCOM. 3542 Snapshot *child = new Snapshot(); 3543 readSnapshot(depth + 1, *pelmChildSnapshot, *child); 3544 snap.llChildSnapshots.push_back(*child); 3545 delete child; 3536 3546 } 3537 3547 } … … 3670 3680 Snapshot snap; 3671 3681 // this will recurse into child snapshots, if necessary 3672 readSnapshot( *pelmMachineChild, snap);3682 readSnapshot(1, *pelmMachineChild, snap); 3673 3683 llFirstSnapshot.push_back(snap); 3674 3684 } … … 4551 4561 && (sc.controllerType == StorageControllerType_I82078) 4552 4562 ) 4553 // floppy controller already got written into <Hardware>/<FloppyController> in writeHardware()4563 // floppy controller already got written into <Hardware>/<FloppyController> in buildHardwareXML() 4554 4564 // for pre-1.9 settings 4555 4565 continue; … … 4751 4761 * for the root snapshot of a machine, if present; elmParent then points to the <Snapshots> node under the 4752 4762 * <Machine> node to which <Snapshot> must be added. This may then recurse for child snapshots. 4763 * 4764 * @param depth 4753 4765 * @param elmParent 4754 4766 * @param snap 4755 4767 */ 4756 void MachineConfigFile::buildSnapshotXML(xml::ElementNode &elmParent, 4768 void MachineConfigFile::buildSnapshotXML(uint32_t depth, 4769 xml::ElementNode &elmParent, 4757 4770 const Snapshot &snap) 4758 4771 { 4772 if (depth > SETTINGS_SNAPSHOT_DEPTH_MAX) 4773 throw ConfigFileError(this, NULL, N_("Maximum snapshot tree depth of %u exceeded"), SETTINGS_SNAPSHOT_DEPTH_MAX); 4774 4759 4775 xml::ElementNode *pelmSnapshot = elmParent.createChild("Snapshot"); 4760 4776 … … 4788 4804 { 4789 4805 const Snapshot &child = *it; 4790 buildSnapshotXML( *pelmChildren, child);4806 buildSnapshotXML(depth + 1, *pelmChildren, child); 4791 4807 } 4792 4808 } … … 4925 4941 if ( (fl & BuildMachineXML_IncludeSnapshots) 4926 4942 && llFirstSnapshot.size()) 4927 buildSnapshotXML( elmMachine, llFirstSnapshot.front());4943 buildSnapshotXML(1, elmMachine, llFirstSnapshot.front()); 4928 4944 4929 4945 buildHardwareXML(elmMachine, hardwareMachine, storageMachine);
Note:
See TracChangeset
for help on using the changeset viewer.