VirtualBox

Changeset 43478 in vbox for trunk/src/VBox/Main


Ignore:
Timestamp:
Oct 1, 2012 9:05:19 AM (12 years ago)
Author:
vboxsync
Message:

Main/Medium: fix race (involving several locks and the object state/caller) between VirtualBox::OpenMedium and Medium::saveSettings. Very tiny window, can only happen after queryInfo has sorted it correctly into the media tree and before the medium was marked as initialized. Also eliminate a race between placing the image in the media tree and updating its UUID to the correct value.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-server/MediumImpl.cpp

    r43476 r43478  
    10191019    AssertReturn(!aLocation.isEmpty(), E_INVALIDARG);
    10201020
    1021     /* Enclose the state transition NotReady->InInit->Ready */
    1022     AutoInitSpan autoInitSpan(this);
    1023     AssertReturn(autoInitSpan.isOk(), E_FAIL);
    1024 
    10251021    HRESULT rc = S_OK;
    10261022
    1027     unconst(m->pVirtualBox) = aVirtualBox;
    1028 
    1029     /* there must be a storage unit */
    1030     m->state = MediumState_Created;
    1031 
    1032     /* remember device type for correct unregistering later */
    1033     m->devType = aDeviceType;
    1034 
    1035     /* cannot be a host drive */
    1036     m->hostDrive = false;
    1037 
    1038     /* remember the open mode (defaults to ReadWrite) */
    1039     m->hddOpenMode = enOpenMode;
    1040 
    1041     if (aDeviceType == DeviceType_DVD)
    1042         m->type = MediumType_Readonly;
    1043     else if (aDeviceType == DeviceType_Floppy)
    1044         m->type = MediumType_Writethrough;
    1045 
    1046     rc = setLocation(aLocation);
    1047     if (FAILED(rc)) return rc;
    1048 
    1049     /* get all the information about the medium from the storage unit */
    1050     if (fForceNewUuid)
    1051         unconst(m->uuidImage).create();
    1052 
     1023    {
     1024        /* Enclose the state transition NotReady->InInit->Ready */
     1025        AutoInitSpan autoInitSpan(this);
     1026        AssertReturn(autoInitSpan.isOk(), E_FAIL);
     1027
     1028        unconst(m->pVirtualBox) = aVirtualBox;
     1029
     1030        /* there must be a storage unit */
     1031        m->state = MediumState_Created;
     1032
     1033        /* remember device type for correct unregistering later */
     1034        m->devType = aDeviceType;
     1035
     1036        /* cannot be a host drive */
     1037        m->hostDrive = false;
     1038
     1039        /* remember the open mode (defaults to ReadWrite) */
     1040        m->hddOpenMode = enOpenMode;
     1041
     1042        if (aDeviceType == DeviceType_DVD)
     1043            m->type = MediumType_Readonly;
     1044        else if (aDeviceType == DeviceType_Floppy)
     1045            m->type = MediumType_Writethrough;
     1046
     1047        rc = setLocation(aLocation);
     1048        if (FAILED(rc)) return rc;
     1049
     1050        /* get all the information about the medium from the storage unit */
     1051        if (fForceNewUuid)
     1052            unconst(m->uuidImage).create();
     1053
     1054        m->state = MediumState_Inaccessible;
     1055        m->strLastAccessError = tr("Accessibility check was not yet performed");
     1056
     1057        /* Confirm a successful initialization before the call to queryInfo.
     1058         * Otherwise we can end up with a AutoCaller deadlock because the
     1059         * medium becomes visible but is not marked as initialized. Causes
     1060         * locking trouble (e.g. trying to save media registries) which is
     1061         * hard to solve. */
     1062        autoInitSpan.setSucceeded();
     1063    }
     1064
     1065    /* we're normal code from now on, no longer init */
     1066    AutoCaller autoCaller(this);
     1067    if (FAILED(autoCaller.rc()))
     1068        return autoCaller.rc();
     1069
     1070    /* need to call queryInfo immediately to correctly place the medium in
     1071     * the respective media tree and update other information such as uuid */
    10531072    rc = queryInfo(fForceNewUuid /* fSetImageId */, false /* fSetParentId */);
    1054 
    10551073    if (SUCCEEDED(rc))
    10561074    {
     1075        AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     1076
    10571077        /* if the storage unit is not accessible, it's not acceptable for the
    10581078         * newly opened media so convert this into an error */
     
    10611081            Assert(!m->strLastAccessError.isEmpty());
    10621082            rc = setError(E_FAIL, "%s", m->strLastAccessError.c_str());
     1083            alock.release();
     1084            autoCaller.release();
     1085            uninit();
    10631086        }
    10641087        else
    10651088        {
    1066             AssertReturn(!m->id.isEmpty(), E_FAIL);
     1089            AssertStmt(!m->id.isEmpty(),
     1090                       alock.release(); autoCaller.release(); uninit(); return E_FAIL);
    10671091
    10681092            /* storage format must be detected by Medium::queryInfo if the
    10691093             * medium is accessible */
    1070             AssertReturn(!m->strFormat.isEmpty(), E_FAIL);
    1071         }
    1072     }
    1073 
    1074     /* Confirm a successful initialization when it's the case */
    1075     if (SUCCEEDED(rc))
    1076         autoInitSpan.setSucceeded();
     1094            AssertStmt(!m->strFormat.isEmpty(),
     1095                       alock.release(); autoCaller.release(); uninit(); return E_FAIL);
     1096        }
     1097    }
     1098    else
     1099    {
     1100        /* opening this image failed, mark the object as dead */
     1101        autoCaller.release();
     1102        uninit();
     1103    }
    10771104
    10781105    return rc;
     
    55635590            }
    55645591
     5592            /* set the image uuid before the below parent uuid handling code
     5593             * might place it somewhere in the media tree, so that the medium
     5594             * UUID is valid at this point */
     5595            alock.acquire();
     5596            if (isImport || fSetImageId)
     5597                unconst(m->id) = mediumId;
     5598            alock.release();
     5599
    55655600            /* get the medium variant */
    55665601            unsigned uImageFlags;
     
    56975732    treeLock.acquire();
    56985733    alock.acquire();
    5699 
    5700     if (isImport || fSetImageId)
    5701         unconst(m->id) = mediumId;
    57025734
    57035735    if (success)
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