VirtualBox

Changeset 98836 in vbox for trunk


Ignore:
Timestamp:
Mar 3, 2023 9:36:21 PM (21 months ago)
Author:
vboxsync
Message:

Main/VirtualBox: Machine::unregister() and VirtualBox::openMachine() can
deadlock while processing a VM's media registry when run concurrently
for the same VM. If openMachine() is registering a differencing hard
disk while unregister() is unregistering the same disk then the two
threads can deadlock. The openMachine() thread can block in
VirtualBox::i_registerMedium() waiting for the media tree lock which the
unregister() thread holds but the unregister() thread can then block in
Medium::i_removeRegistryAll() waiting for the medium object to move out
of the 'InInit' state which the openMachine() thread will do once it
acquires the media tree lock so they are deadlocked. The fix is to
close the window of opportunity in VirtualBox::i_registerMedium() by not
dropping the media tree lock when called by Medium::initFromSettings().
bugref:6447

File:
1 edited

Legend:

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

    r98351 r98836  
    51375137        if (devType == DeviceType_HardDisk)
    51385138            m->mapHardDisks[id] = pMedium;
    5139 
    5140         mediumCaller.release();
    5141         mediaTreeLock.release();
    5142         *ppMedium = pMedium;
    5143     }
    5144     else
     5139    }
     5140
     5141    /*
     5142     * If we have been called from Medium::initFromSettings() then the Medium object's
     5143     * AutoCaller status will be 'InInit' which means that when making the assigment to
     5144     * ppMedium below the Medium object will not call Medium::uninit().  By excluding
     5145     * this code path from releasing and reacquiring the media tree lock we avoid a
     5146     * potential deadlock with other threads which may be operating on the
     5147     * disks/DVDs/floppies in the VM's media registry at the same time such as
     5148     * Machine::unregister().
     5149     */
     5150    if (!fCalledFromMediumInit)
    51455151    {
    51465152        // pMedium may be the last reference to the Medium object, and the
     
    51535159        // must not hold the media tree write lock any more
    51545160        Assert(!i_getMediaTreeLockHandle().isWriteLockOnCurrentThread());
    5155         *ppMedium = pDupMedium;
    5156     }
     5161    }
     5162
     5163    *ppMedium = pDupMedium.isNull() ? pMedium : pDupMedium;
    51575164
    51585165    if (fAddToGlobalRegistry)
     
    51675174    // Restore the initial lock state, so that no unexpected lock changes are
    51685175    // done by this method, which would need adjustments everywhere.
    5169     mediaTreeLock.acquire();
     5176    if (!fCalledFromMediumInit)
     5177        mediaTreeLock.acquire();
    51705178
    51715179    return hrc;
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