VirtualBox

Changeset 102533 in vbox for trunk/src


Ignore:
Timestamp:
Dec 8, 2023 10:15:02 AM (17 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
160677
Message:

Main/Guest Control: Fixed a shutdown race when uninitializing guest sessions via IGuestSession::Close(): There we need to check if its parent object (IGuest) still is around and in a working shape, and if not, do the cleanup stuff ourselves. Renamed Guest::i_sessionDestroy() -> Guest::i_sessionRemove() to make its function more clear. This race seemed to happen in combination with FE/Qt's guest file manager every now and then. bugref:9135

Location:
trunk/src/VBox/Main
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/src/VBox/Main/include/GuestImpl.h

    r98103 r102533  
    131131    int         i_sessionCreate(const GuestSessionStartupInfo &ssInfo, const GuestCredentials &guestCreds,
    132132                                ComObjPtr<GuestSession> &pGuestSession);
    133     int         i_sessionDestroy(uint32_t uSessionID);
     133    int         i_sessionRemove(uint32_t uSessionID);
    134134    inline bool i_sessionExists(uint32_t uSessionID);
    135135    /** Returns the VBOX_GUESTCTRL_GF_0_XXX mask reported by the guest. */
  • TabularUnified trunk/src/VBox/Main/src-client/GuestCtrlImpl.cpp

    r99416 r102533  
    350350
    351351/**
    352  * Destroys a given guest session and removes it from the internal list.
     352 * Removes a given guest session and removes it from the internal list.
    353353 *
    354354 * @returns VBox status code.
    355355 * @param   uSessionID          ID of the guest control session to destroy.
    356356 *
    357  * @note    Takes the write lock.
     357 * @note    Takes the read + write locks.
    358358 */
    359 int Guest::i_sessionDestroy(uint32_t uSessionID)
     359int Guest::i_sessionRemove(uint32_t uSessionID)
    360360{
    361361    LogFlowThisFuncEnter();
    362362
    363     AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    364 
    365363    int vrc = VERR_NOT_FOUND;
    366364
    367     LogFlowThisFunc(("Destroying session (ID=%RU32) ...\n", uSessionID));
     365    LogFlowThisFunc(("Removing session (ID=%RU32) ...\n", uSessionID));
     366
     367    AutoReadLock arlock(this COMMA_LOCKVAL_SRC_POS);
    368368
    369369    GuestSessions::iterator itSessions = mData.mGuestSessions.find(uSessionID);
     
    379379
    380380    vrc = pSession->i_onRemove();
     381
     382    arlock.release();
     383
     384    AutoWriteLock awlock(this COMMA_LOCKVAL_SRC_POS);
    381385    mData.mGuestSessions.erase(itSessions);
    382 
    383     alock.release(); /* Release lock before firing off event. */
     386    awlock.release(); /* Release write lock before firing off event. */
    384387
    385388    ::FireGuestSessionRegisteredEvent(mEventSource, pSession, false /* Unregistered */);
  • TabularUnified trunk/src/VBox/Main/src-client/GuestImpl.cpp

    r99739 r102533  
    188188    {
    189189# ifdef DEBUG
    190 /** @todo r=bird: hit a use-after-free situation here while debugging the
    191  * 0xcccccccc status code issue in copyto.  My bet is that this happens
    192  * because of an uninit race, where GuestSession::close(), or someone, does
    193  * not ensure that the parent object (Guest) is okay to use (in the AutoCaller
    194  * sense), only their own object. */
    195190        ULONG cRefs = itSessions->second->AddRef();
    196191        LogFlowThisFunc(("sessionID=%RU32, cRefs=%RU32\n", itSessions->first, cRefs > 1 ? cRefs - 1 : 0));
  • TabularUnified trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r100325 r102533  
    320320void GuestSession::uninit(void)
    321321{
     322    LogFlowThisFuncEnter();
     323
    322324    /* Enclose the state transition Ready->InUninit->NotReady. */
    323325    AutoUninitSpan autoUninitSpan(this);
    324326    if (autoUninitSpan.uninitDone())
    325327        return;
    326 
    327     LogFlowThisFuncEnter();
    328328
    329329    /* Call i_onRemove to take care of the object cleanups. */
     
    33743374
    33753375#ifndef VBOX_GUESTCTRL_TEST_CASE
     3376    AutoCaller autoCallerParent(mParent);
     3377    if (FAILED(autoCallerParent.hrc()))
     3378        return VERR_STATE_CHANGED;
     3379
    33763380    ComObjPtr<Console> pConsole = mParent->i_getConsole();
    33773381    Assert(!pConsole.isNull());
     
    33793383    /* Forward the information to the VMM device. */
    33803384    VMMDev *pVMMDev = pConsole->i_getVMMDev();
    3381     AssertPtrReturn(pVMMDev, VERR_STATE_CHANGED);
     3385    if (!pVMMDev)
     3386        return VERR_STATE_CHANGED;
    33823387
    33833388    LogFlowThisFunc(("uMessage=%RU32 (%s), uParms=%RU32\n", uMessage, GstCtrlHostMsgtoStr((guestControl::eHostMsg)uMessage), uParms));
     
    38513856HRESULT GuestSession::close()
    38523857{
     3858    AutoCaller autoCaller(this);
     3859    if (FAILED(autoCaller.hrc())) return autoCaller.hrc();
     3860
    38533861    LogFlowThisFuncEnter();
    38543862
     
    38793887     * work first and then return an error. */
    38803888
    3881     /* Destroy session + remove ourselves from the session list. */
    3882     AssertPtr(mParent);
    3883     int vrc2 = mParent->i_sessionDestroy(mData.mSession.mID);
    3884     if (vrc2 == VERR_NOT_FOUND) /* Not finding the session anymore isn't critical. */
    3885         vrc2 = VINF_SUCCESS;
    3886 
    3887     if (RT_SUCCESS(vrc))
    3888         vrc = vrc2;
     3889    /* We have to make sure that our parent (IGuest) still is alive and in a working shapee.
     3890     * If not, skip removing the session from it. */
     3891    AutoCaller autoCallerParent(mParent);
     3892    if (SUCCEEDED(autoCallerParent.hrc()))
     3893    {
     3894        LogFlowThisFunc(("Removing session '%s' from parent ...", mData.mSession.mName.c_str()));
     3895
     3896        /* Remove ourselves from the session list. */
     3897        AssertPtr(mParent);
     3898        int vrc2 = mParent->i_sessionRemove(mData.mSession.mID);
     3899        if (vrc2 == VERR_NOT_FOUND) /* Not finding the session anymore isn't critical. */
     3900            vrc2 = VINF_SUCCESS;
     3901
     3902        if (RT_SUCCESS(vrc))
     3903            vrc = vrc2;
     3904    }
     3905    else /* Do the session remove stuff ourselves. */
     3906        vrc = i_onRemove();
    38893907
    38903908    LogFlowThisFunc(("Returning vrc=%Rrc, vrcGuest=%Rrc\n", vrc, vrcGuest));
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette