Changeset 52095 in vbox
- Timestamp:
- Jul 18, 2014 9:14:01 AM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 95105
- Location:
- trunk/src/VBox/Main
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/idl/VirtualBox.xidl
r52090 r52095 13658 13658 </attribute> 13659 13659 13660 <attribute name="parent" type="IMedium" readonly="yes" >13660 <attribute name="parent" type="IMedium" readonly="yes" wrap-hint-server="passcaller"> 13661 13661 <desc> 13662 13662 Parent of this medium (the medium this medium is directly based … … 13668 13668 </attribute> 13669 13669 13670 <attribute name="children" type="IMedium" safearray="yes" readonly="yes" >13670 <attribute name="children" type="IMedium" safearray="yes" readonly="yes" wrap-hint-server="passcaller"> 13671 13671 <desc> 13672 13672 Children of this medium (all differencing media directly based … … 13676 13676 </attribute> 13677 13677 13678 <attribute name="base" type="IMedium" readonly="yes" >13678 <attribute name="base" type="IMedium" readonly="yes" wrap-hint-server="passcaller"> 13679 13679 <desc> 13680 13680 Base medium of this medium. -
trunk/src/VBox/Main/include/AutoCaller.h
r51903 r52095 475 475 bool uninitDone() { return mUninitDone; } 476 476 477 void setSucceeded(); 478 477 479 private: 478 480 -
trunk/src/VBox/Main/include/VirtualBoxImpl.h
r50380 r52095 214 214 int i_calculateFullPath(const Utf8Str &strPath, Utf8Str &aResult); 215 215 void i_copyPathRelativeToConfig(const Utf8Str &strSource, Utf8Str &strTarget); 216 HRESULT i_registerMedium(const ComObjPtr<Medium> &pMedium, ComObjPtr<Medium> *ppMedium, DeviceType_T argType );216 HRESULT i_registerMedium(const ComObjPtr<Medium> &pMedium, ComObjPtr<Medium> *ppMedium, DeviceType_T argType, AutoWriteLock &mediaTreeLock); 217 217 HRESULT i_unregisterMedium(Medium *pMedium); 218 218 void i_pushMediumToListWithChildren(MediaList &llMedia, Medium *pMedium); -
trunk/src/VBox/Main/src-all/AutoCaller.cpp
r52029 r52095 498 498 mObj->getObjectState().autoUninitSpanDestructor(); 499 499 } 500 501 /** 502 * Marks the uninitializion as succeeded. 503 * 504 * Same as the destructor, and makes the destructor do nothing. 505 */ 506 void AutoUninitSpan::setSucceeded() 507 { 508 /* do nothing if already uninitialized */ 509 if (mUninitDone) 510 return; 511 512 mObj->getObjectState().autoUninitSpanDestructor(); 513 mUninitDone = true; 514 } -
trunk/src/VBox/Main/src-server/MachineImplCloneVM.cpp
r51498 r52095 1250 1250 AutoWriteLock tlock(p->mParent->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 1251 1251 rc = p->mParent->i_registerMedium(pTarget, &pTarget, 1252 DeviceType_HardDisk); 1252 DeviceType_HardDisk, 1253 tlock); 1253 1254 if (FAILED(rc)) throw rc; 1254 1255 } -
trunk/src/VBox/Main/src-server/MediumImpl.cpp
r52078 r52095 934 934 if (FAILED(rc)) return rc; 935 935 936 if (!(m->formatObj->i_getCapabilities() & ( 937 | MediumFormatCapabilities_CreateDynamic))936 if (!(m->formatObj->i_getCapabilities() & ( MediumFormatCapabilities_CreateFixed 937 | MediumFormatCapabilities_CreateDynamic)) 938 938 ) 939 939 { … … 970 970 } 971 971 972 rc = m->pVirtualBox->i_registerMedium(this, &pMedium, DeviceType_HardDisk );972 rc = m->pVirtualBox->i_registerMedium(this, &pMedium, DeviceType_HardDisk, treeLock); 973 973 Assert(this == pMedium || FAILED(rc)); 974 974 } … … 1266 1266 * get the actual state and the rest of the data, the user will have to call 1267 1267 * COMGETTER(State). */ 1268 1269 AutoWriteLock treeLock(aVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);1270 1268 1271 1269 /* load all children */ … … 1286 1284 if (FAILED(rc)) break; 1287 1285 1288 rc = m->pVirtualBox->i_registerMedium(pHD, &pHD, DeviceType_HardDisk); 1286 AutoWriteLock treeLock(aVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 1287 1288 rc = m->pVirtualBox->i_registerMedium(pHD, &pHD, DeviceType_HardDisk, treeLock); 1289 1289 if (FAILED(rc)) break; 1290 1290 } … … 1368 1368 void Medium::uninit() 1369 1369 { 1370 /* It is possible that some previous/concurrent uninit has already cleared 1371 * the pVirtualBox reference, and in this case we don't need to continue. 1372 * Normally this would be handled through the AutoUninitSpan magic, 1373 * however this cannot be done at this point as the media tree must be 1374 * locked before reaching the AutoUninitSpan, otherwise deadlocks can 1375 * happen due to*/ 1376 ComObjPtr<VirtualBox> pVirtualBox(m->pVirtualBox); 1377 if (!pVirtualBox) 1378 return; 1379 1380 /* Caller must not hold the object or media tree lock over uninit(). */ 1381 Assert(!isWriteLockOnCurrentThread()); 1382 Assert(!pVirtualBox->i_getMediaTreeLockHandle().isWriteLockOnCurrentThread()); 1383 1384 AutoWriteLock treeLock(pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 1385 1370 1386 /* Enclose the state transition Ready->InUninit->NotReady */ 1371 1387 AutoUninitSpan autoUninitSpan(this); … … 1374 1390 1375 1391 if (!m->formatObj.isNull()) 1376 {1377 /* remove the caller reference we added in setFormat() */1378 m->formatObj->getObjectState().releaseCaller();1379 1392 m->formatObj.setNull(); 1380 }1381 1393 1382 1394 if (m->state == MediumState_Deleting) … … 1388 1400 else 1389 1401 { 1390 MediaList::iterator it; 1391 for (it = m->llChildren.begin(); 1392 it != m->llChildren.end(); 1393 ++it) 1394 { 1395 Medium *pChild = *it; 1402 MediaList llChildren(m->llChildren); 1403 m->llChildren.clear(); 1404 autoUninitSpan.setSucceeded(); 1405 1406 while (!llChildren.empty()) 1407 { 1408 ComObjPtr<Medium> pChild = llChildren.front(); 1409 llChildren.pop_front(); 1396 1410 pChild->m->pParent.setNull(); 1411 treeLock.release(); 1397 1412 pChild->uninit(); 1398 }1399 m->llChildren.clear(); // this unsets all the ComPtrs and probably calls delete1413 treeLock.acquire(); 1414 } 1400 1415 1401 1416 if (m->pParent) … … 1713 1728 } 1714 1729 1715 HRESULT Medium::getParent(ComPtr<IMedium> &aParent) 1716 { 1730 HRESULT Medium::getParent(AutoCaller &autoCaller, ComPtr<IMedium> &aParent) 1731 { 1732 autoCaller.release(); 1733 1734 /* It is possible that some previous/concurrent uninit has already cleared 1735 * the pVirtualBox reference, see #uninit(). */ 1736 ComObjPtr<VirtualBox> pVirtualBox(m->pVirtualBox); 1737 1717 1738 /* we access mParent */ 1718 AutoReadLock treeLock(m->pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 1739 AutoReadLock treeLock(!pVirtualBox.isNull() ? &pVirtualBox->i_getMediaTreeLockHandle() : NULL COMMA_LOCKVAL_SRC_POS); 1740 1741 autoCaller.add(); 1742 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1719 1743 1720 1744 m->pParent.queryInterfaceTo(aParent.asOutParam()); … … 1723 1747 } 1724 1748 1725 HRESULT Medium::getChildren(std::vector<ComPtr<IMedium> > &aChildren) 1726 { 1749 HRESULT Medium::getChildren(AutoCaller &autoCaller, std::vector<ComPtr<IMedium> > &aChildren) 1750 { 1751 autoCaller.release(); 1752 1753 /* It is possible that some previous/concurrent uninit has already cleared 1754 * the pVirtualBox reference, see #uninit(). */ 1755 ComObjPtr<VirtualBox> pVirtualBox(m->pVirtualBox); 1756 1727 1757 /* we access children */ 1728 AutoReadLock treeLock(m->pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 1758 AutoReadLock treeLock(!pVirtualBox.isNull() ? &pVirtualBox->i_getMediaTreeLockHandle() : NULL COMMA_LOCKVAL_SRC_POS); 1759 1760 autoCaller.add(); 1761 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 1729 1762 1730 1763 MediaList children(this->i_getChildren()); … … 1736 1769 } 1737 1770 1738 HRESULT Medium::getBase(ComPtr<IMedium> &aBase) 1739 { 1771 HRESULT Medium::getBase(AutoCaller &autoCaller, ComPtr<IMedium> &aBase) 1772 { 1773 autoCaller.release(); 1774 1740 1775 /* i_getBase() will do callers/locking */ 1741 1776 i_getBase().queryInterfaceTo(aBase.asOutParam()); … … 3229 3264 } 3230 3265 3266 autoCaller.release(); 3267 3231 3268 /* Save the error information now, the implicit restore when this goes 3232 3269 * out of scope will throw away spurious additional errors created below. */ … … 3523 3560 { 3524 3561 ComObjPtr<Medium> pBase; 3525 uint32_t level; 3562 3563 /* it is possible that some previous/concurrent uninit has already cleared 3564 * the pVirtualBox reference, and in this case we don't need to continue */ 3565 ComObjPtr<VirtualBox> pVirtualBox(m->pVirtualBox); 3566 if (!pVirtualBox) 3567 return pBase; 3568 3569 /* we access mParent */ 3570 AutoReadLock treeLock(pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 3526 3571 3527 3572 AutoCaller autoCaller(this); 3528 3573 AssertReturn(autoCaller.isOk(), pBase); 3529 3574 3530 /* we access mParent */3531 AutoReadLock treeLock(m->pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);3532 3533 3575 pBase = this; 3534 level = 0;3576 uint32_t level = 0; 3535 3577 3536 3578 if (m->pParent) … … 3971 4013 HRESULT Medium::i_close(AutoCaller &autoCaller) 3972 4014 { 4015 // must temporarily drop the caller, need the tree lock first 4016 autoCaller.release(); 4017 3973 4018 // we're accessing parent/child and backrefs, so lock the tree first, then ourselves 3974 4019 AutoMultiWriteLock2 multilock(&m->pVirtualBox->i_getMediaTreeLockHandle(), 3975 4020 this->lockHandle() 3976 4021 COMMA_LOCKVAL_SRC_POS); 4022 4023 autoCaller.add(); 4024 if (FAILED(autoCaller.rc())) return autoCaller.rc(); 3977 4025 3978 4026 LogFlowFunc(("ENTER for %s\n", i_getLocationFull().c_str())); … … 4010 4058 4011 4059 multilock.release(); 4060 // Release the AutoCaller now, as otherwise uninit() will simply hang. 4061 // Needs to be done before mark the registries as modified and saving 4062 // the registry, as otherwise there may be a deadlock with someone else 4063 // closing this object while we're in i_saveModifiedRegistries(), which 4064 // needs the media tree lock, which the other thread holds until after 4065 // uninit() below. 4066 autoCaller.release(); 4012 4067 i_markRegistriesModified(); 4013 // Release the AutoCalleri now, as otherwise uninit() will simply hang.4014 // Needs to be done before saving the registry, as otherwise there4015 // may be a deadlock with someone else closing this object while we're4016 // in i_saveModifiedRegistries(), which needs the media tree lock, which4017 // the other thread holds until after uninit() below.4018 // @todo redesign the locking here, as holding the locks over uninit4019 // causes lock order trouble which the lock validator can't detect4020 autoCaller.release();4021 4068 m->pVirtualBox->i_saveModifiedRegistries(); 4022 multilock.acquire();4023 4069 } 4024 4070 else 4025 4071 { 4072 multilock.release(); 4026 4073 // release the AutoCaller, as otherwise uninit() will simply hang 4027 4074 autoCaller.release(); … … 4079 4126 LogFlowThisFunc(("aWait=%RTbool locationFull=%s\n", aWait, i_getLocationFull().c_str() )); 4080 4127 4081 if ( !(m->formatObj->i_getCapabilities() & ( 4082 | MediumFormatCapabilities_CreateFixed)))4128 if ( !(m->formatObj->i_getCapabilities() & ( MediumFormatCapabilities_CreateDynamic 4129 | MediumFormatCapabilities_CreateFixed))) 4083 4130 throw setError(VBOX_E_NOT_SUPPORTED, 4084 4131 tr("Medium format '%s' does not support storage deletion"), … … 6176 6223 aFormat.c_str()); 6177 6224 6178 /* reference the format permanently to prevent its unexpected6179 * uninitialization */6180 HRESULT rc = m->formatObj->getObjectState().addCaller(m->formatObj);6181 AssertComRCReturnRC(rc);6182 6183 6225 /* get properties (preinsert them as keys in the map). Note that the 6184 6226 * map doesn't grow over the object life time since the set of … … 6676 6718 AutoWriteLock treeLock(m->pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 6677 6719 ComObjPtr<Medium> pMedium; 6678 rc = m->pVirtualBox->i_registerMedium(this, &pMedium, DeviceType_HardDisk );6720 rc = m->pVirtualBox->i_registerMedium(this, &pMedium, DeviceType_HardDisk, treeLock); 6679 6721 Assert(this == pMedium); 6680 6722 } … … 6863 6905 * better than breaking media registry consistency) */ 6864 6906 ComObjPtr<Medium> pMedium; 6865 mrc = m->pVirtualBox->i_registerMedium(pTarget, &pMedium, DeviceType_HardDisk );6907 mrc = m->pVirtualBox->i_registerMedium(pTarget, &pMedium, DeviceType_HardDisk, treeLock); 6866 6908 Assert(pTarget == pMedium); 6867 6909 … … 7098 7140 ComObjPtr<Medium> pMedium; 7099 7141 rc2 = m->pVirtualBox->i_registerMedium(pTarget, &pMedium, 7100 DeviceType_HardDisk); 7142 DeviceType_HardDisk, 7143 treeLock); 7101 7144 AssertComRC(rc2); 7102 7145 } … … 7182 7225 7183 7226 if (task.isAsync() || pMedium != this) 7227 { 7228 treeLock.release(); 7184 7229 pMedium->uninit(); 7230 treeLock.acquire(); 7231 } 7185 7232 } 7186 7233 } … … 7426 7473 { 7427 7474 /* we set mParent & children() */ 7428 AutoWriteLock alock2(m->pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);7475 AutoWriteLock treeLock(m->pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 7429 7476 7430 7477 Assert(pTarget->m->pParent.isNull()); … … 7443 7490 ComObjPtr<Medium> pMedium; 7444 7491 mrc = pParent->m->pVirtualBox->i_registerMedium(pTarget, &pMedium, 7445 DeviceType_HardDisk); 7492 DeviceType_HardDisk, 7493 treeLock); 7446 7494 Assert( FAILED(mrc) 7447 7495 || pTarget == pMedium); … … 7458 7506 ComObjPtr<Medium> pMedium; 7459 7507 mrc = m->pVirtualBox->i_registerMedium(pTarget, &pMedium, 7460 DeviceType_HardDisk); 7508 DeviceType_HardDisk, 7509 treeLock); 7461 7510 Assert( FAILED(mrc) 7462 7511 || pTarget == pMedium); … … 8214 8263 { 8215 8264 /* we set mParent & children() */ 8216 AutoWriteLock alock2(m->pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS);8265 AutoWriteLock treeLock(m->pVirtualBox->i_getMediaTreeLockHandle() COMMA_LOCKVAL_SRC_POS); 8217 8266 8218 8267 Assert(m->pParent.isNull()); … … 8231 8280 ComObjPtr<Medium> pMedium; 8232 8281 mrc = pParent->m->pVirtualBox->i_registerMedium(this, &pMedium, 8233 DeviceType_HardDisk); 8282 DeviceType_HardDisk, 8283 treeLock); 8234 8284 Assert(this == pMedium); 8235 8285 eik.fetch(); 8236 8286 8237 8287 if (FAILED(mrc)) 8288 { 8289 treeLock.acquire(); 8238 8290 /* break parent association on failure to register */ 8239 8291 this->i_deparent(); // removes target from parent 8292 } 8240 8293 } 8241 8294 else … … 8244 8297 eik.restore(); 8245 8298 ComObjPtr<Medium> pMedium; 8246 mrc = m->pVirtualBox->i_registerMedium(this, &pMedium, DeviceType_HardDisk );8299 mrc = m->pVirtualBox->i_registerMedium(this, &pMedium, DeviceType_HardDisk, treeLock); 8247 8300 Assert(this == pMedium); 8248 8301 eik.fetch(); -
trunk/src/VBox/Main/src-server/SnapshotImpl.cpp
r51903 r52095 3469 3469 3470 3470 // then, register again 3471 rc = mParent->i_registerMedium(pDeleteRec->mpTarget, &pDeleteRec->mpTarget, DeviceType_HardDisk );3471 rc = mParent->i_registerMedium(pDeleteRec->mpTarget, &pDeleteRec->mpTarget, DeviceType_HardDisk, treeLock); 3472 3472 AssertComRC(rc); 3473 treeLock.acquire(); 3473 3474 } 3474 3475 else -
trunk/src/VBox/Main/src-server/VirtualBoxImpl.cpp
r51903 r52095 675 675 if (FAILED(rc)) return rc; 676 676 677 rc = i_registerMedium(pHardDisk, &pHardDisk, DeviceType_HardDisk );677 rc = i_registerMedium(pHardDisk, &pHardDisk, DeviceType_HardDisk, treeLock); 678 678 if (FAILED(rc)) return rc; 679 679 } … … 695 695 if (FAILED(rc)) return rc; 696 696 697 rc = i_registerMedium(pImage, &pImage, DeviceType_DVD );697 rc = i_registerMedium(pImage, &pImage, DeviceType_DVD, treeLock); 698 698 if (FAILED(rc)) return rc; 699 699 } … … 715 715 if (FAILED(rc)) return rc; 716 716 717 rc = i_registerMedium(pImage, &pImage, DeviceType_Floppy );717 rc = i_registerMedium(pImage, &pImage, DeviceType_Floppy, treeLock); 718 718 if (FAILED(rc)) return rc; 719 719 } … … 1831 1831 if (SUCCEEDED(rc)) 1832 1832 { 1833 rc = i_registerMedium(pMedium, &pMedium, aDeviceType );1833 rc = i_registerMedium(pMedium, &pMedium, aDeviceType, treeLock); 1834 1834 1835 1835 treeLock.release(); … … 2948 2948 2949 2949 /** 2950 * @note Locks th is objectfor reading.2950 * @note Locks the list of other objects for reading. 2951 2951 */ 2952 2952 ComObjPtr<GuestOSType> VirtualBox::i_getUnknownOSType() 2953 2953 { 2954 2954 ComObjPtr<GuestOSType> type; 2955 AutoCaller autoCaller(this);2956 AssertComRCReturn(autoCaller.rc(), type);2957 2955 2958 2956 /* unknown type must always be the first */ … … 4155 4153 * created. 4156 4154 * @param argType Either DeviceType_HardDisk, DeviceType_DVD or DeviceType_Floppy. 4155 * @param mediaTreeLock Reference to the AutoWriteLock holding the media tree 4156 * lock, necessary to release it in the right spot. 4157 4157 * @return 4158 4158 */ 4159 4159 HRESULT VirtualBox::i_registerMedium(const ComObjPtr<Medium> &pMedium, 4160 4160 ComObjPtr<Medium> *ppMedium, 4161 DeviceType_T argType) 4161 DeviceType_T argType, 4162 AutoWriteLock &mediaTreeLock) 4162 4163 { 4163 4164 AssertReturn(pMedium != NULL, E_INVALIDARG); 4164 4165 AssertReturn(ppMedium != NULL, E_INVALIDARG); 4166 4167 // caller must hold the media tree write lock 4168 Assert(i_getMediaTreeLockHandle().isWriteLockOnCurrentThread()); 4165 4169 4166 4170 AutoCaller autoCaller(this); … … 4190 4194 } 4191 4195 4192 // caller must hold the media tree write lock4193 Assert(i_getMediaTreeLockHandle().isWriteLockOnCurrentThread());4194 4195 4196 Guid id; 4196 4197 Utf8Str strLocationFull; … … 4232 4233 m->mapHardDisks[id] = pMedium; 4233 4234 4235 mediumCaller.release(); 4236 mediaTreeLock.release(); 4234 4237 *ppMedium = pMedium; 4235 4238 } … … 4241 4244 // have a caller pending. 4242 4245 mediumCaller.release(); 4246 // release media tree lock, must not be held at uninit time. 4247 mediaTreeLock.release(); 4248 // must not hold the media tree write lock any more 4249 Assert(!i_getMediaTreeLockHandle().isWriteLockOnCurrentThread()); 4243 4250 *ppMedium = pDupMedium; 4244 4251 } … … 4800 4807 AssertComRCReturn(autoCaller.rc(), autoCaller.rc()); 4801 4808 4809 // need it below, in findDHCPServerByNetworkName (reading) and in 4810 // m->allDHCPServers.addChild, so need to get it here to avoid lock 4811 // order trouble with dhcpServerCaller 4812 AutoWriteLock alock(m->allDHCPServers.getLockHandle() COMMA_LOCKVAL_SRC_POS); 4813 4802 4814 AutoCaller dhcpServerCaller(aDHCPServer); 4803 4815 AssertComRCReturn(dhcpServerCaller.rc(), dhcpServerCaller.rc());
Note:
See TracChangeset
for help on using the changeset viewer.