VirtualBox

Changeset 66857 in vbox for trunk/src/VBox/Main/src-client


Ignore:
Timestamp:
May 10, 2017 11:07:03 AM (8 years ago)
Author:
vboxsync
Message:

Guest Control/Main: Event fixes (for bugref:8833):

  • Check for context ID collisions in registerWaitEvent().
  • Remove the event from the general event list as well in unregisterWaitEvent().
  • Take the critical section in signalWaitEventInternalEx().
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-client/GuestCtrlPrivate.cpp

    r63258 r66857  
    55
    66/*
    7  * Copyright (C) 2011-2016 Oracle Corporation
     7 * Copyright (C) 2011-2017 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    716716}
    717717
     718/**
     719 * Registers (creates) a new wait event based on a given session and object ID.
     720 *
     721 * From those IDs an unique context ID (CID) will be built, which only can be
     722 * around once at a time.
     723 *
     724 * @returns IPRT status code. VERR_ALREADY_EXISTS if an event with the given session
     725 *          and object ID already has been registered.
     726 *
     727 * @param   uSessionID              Session ID to register wait event for.
     728 * @param   uObjectID               Object ID to register wait event for.
     729 * @param   lstEvents               List of events to register the wait event for.
     730 * @param   ppEvent                 Pointer to registered (created) wait event on success.
     731 *                                  Must be destroyed with unregisterWaitEvent().
     732 */
    718733int GuestBase::registerWaitEvent(uint32_t uSessionID, uint32_t uObjectID,
    719734                                 const GuestEventTypes &lstEvents,
     
    742757                 itEvents != lstEvents.end(); ++itEvents)
    743758            {
    744                 mWaitEventGroups[(*itEvents)].insert(
    745                    std::pair<uint32_t, GuestWaitEvent*>(uContextID, pEvent));
    746                 /** @todo Check for key collision. */
     759                /* Check if the event group already has an event with the same
     760                 * context ID in it (collision). */
     761                GuestWaitEvents eventGroup = mWaitEventGroups[(*itEvents)];
     762                if (eventGroup.find(uContextID) == eventGroup.end())
     763                {
     764                    /* No, insert. */
     765                    mWaitEventGroups[(*itEvents)].insert(std::pair<uint32_t, GuestWaitEvent *>(uContextID, pEvent));
     766                }
     767                else
     768                {
     769                    rc = VERR_ALREADY_EXISTS;
     770                    break;
     771                }
    747772            }
    748773
    749             /* Register event in regular event list. */
    750             /** @todo Check for key collisions. */
    751             mWaitEvents[uContextID] = pEvent;
    752 
    753             *ppEvent = pEvent;
     774            if (RT_SUCCESS(rc))
     775            {
     776                /* Register event in regular event list. */
     777                if (mWaitEvents.find(uContextID) == mWaitEvents.end())
     778                {
     779                    mWaitEvents[uContextID] = pEvent;
     780                }
     781                else
     782                    rc  = VERR_ALREADY_EXISTS;
     783            }
     784
     785            if (RT_SUCCESS(rc))
     786                *ppEvent = pEvent;
    754787        }
    755788        catch(std::bad_alloc &)
     
    860893    /* pPayload is optional. */
    861894
    862     int rc2;
    863     GuestWaitEvents::iterator itEvent = mWaitEvents.find(pCbCtx->uContextID);
    864     if (itEvent != mWaitEvents.end())
    865     {
    866         LogFlowThisFunc(("Signalling event=%p (CID %RU32, rc=%Rrc, guestRc=%Rrc, pPayload=%p) ...\n",
    867                          itEvent->second, itEvent->first, rc, guestRc, pPayload));
    868         GuestWaitEvent *pEvent = itEvent->second;
    869         AssertPtr(pEvent);
    870         rc2 = pEvent->SignalInternal(rc, guestRc, pPayload);
    871     }
    872     else
    873         rc2 = VERR_NOT_FOUND;
     895    int rc2 = RTCritSectEnter(&mWaitEventCritSect);
     896    if (RT_SUCCESS(rc2))
     897    {
     898        GuestWaitEvents::iterator itEvent = mWaitEvents.find(pCbCtx->uContextID);
     899        if (itEvent != mWaitEvents.end())
     900        {
     901            LogFlowThisFunc(("Signalling event=%p (CID %RU32, rc=%Rrc, guestRc=%Rrc, pPayload=%p) ...\n",
     902                             itEvent->second, itEvent->first, rc, guestRc, pPayload));
     903            GuestWaitEvent *pEvent = itEvent->second;
     904            AssertPtr(pEvent);
     905            rc2 = pEvent->SignalInternal(rc, guestRc, pPayload);
     906        }
     907        else
     908            rc2 = VERR_NOT_FOUND;
     909
     910        int rc3 = RTCritSectLeave(&mWaitEventCritSect);
     911        if (RT_SUCCESS(rc2))
     912            rc2 = rc3;
     913    }
    874914
    875915    return rc2;
    876916}
    877917
    878 void GuestBase::unregisterWaitEvent(GuestWaitEvent *pEvent)
     918/**
     919 * Unregisters (deletes) a wait event.
     920 *
     921 * After successful unregistration the event will not be valid anymore.
     922 *
     923 * @returns IPRT status code.
     924 * @param   pEvent                  Event to unregister (delete).
     925 */
     926int GuestBase::unregisterWaitEvent(GuestWaitEvent *pEvent)
    879927{
    880928    if (!pEvent) /* Nothing to unregister. */
    881         return;
     929        return VINF_SUCCESS;
    882930
    883931    int rc = RTCritSectEnter(&mWaitEventCritSect);
     
    886934        LogFlowThisFunc(("pEvent=%p\n", pEvent));
    887935
    888         const GuestEventTypes lstTypes = pEvent->Types();
    889         for (GuestEventTypes::const_iterator itEvents = lstTypes.begin();
    890              itEvents != lstTypes.end(); ++itEvents)
    891         {
    892             /** @todo Slow O(n) lookup. Optimize this. */
    893             GuestWaitEvents::iterator itCurEvent = mWaitEventGroups[(*itEvents)].begin();
    894             while (itCurEvent != mWaitEventGroups[(*itEvents)].end())
     936        try
     937        {
     938            /* Remove the event from all event type groups. */
     939            const GuestEventTypes lstTypes = pEvent->Types();
     940            for (GuestEventTypes::const_iterator itType = lstTypes.begin();
     941                 itType != lstTypes.end(); ++itType)
    895942            {
    896                 if (itCurEvent->second == pEvent)
     943                /** @todo Slow O(n) lookup. Optimize this. */
     944                GuestWaitEvents::iterator itCurEvent = mWaitEventGroups[(*itType)].begin();
     945                while (itCurEvent != mWaitEventGroups[(*itType)].end())
    897946                {
    898                     mWaitEventGroups[(*itEvents)].erase(itCurEvent++);
    899                     break;
     947                    if (itCurEvent->second == pEvent)
     948                    {
     949                        mWaitEventGroups[(*itType)].erase(itCurEvent++);
     950                        break;
     951                    }
     952                    else
     953                        ++itCurEvent;
    900954                }
    901                 else
    902                     ++itCurEvent;
    903955            }
    904         }
    905 
    906         delete pEvent;
    907         pEvent = NULL;
     956
     957            /* Remove the event from the general event list as well. */
     958            GuestWaitEvents::iterator itEvent = mWaitEvents.find(pEvent->ContextID());
     959
     960            Assert(itEvent != mWaitEvents.end());
     961            Assert(itEvent->second == pEvent);
     962
     963            mWaitEvents.erase(itEvent);
     964
     965            delete pEvent;
     966            pEvent = NULL;
     967        }
     968        catch (const std::exception &ex)
     969        {
     970            NOREF(ex);
     971            AssertFailedStmt(rc = VERR_NOT_FOUND);
     972        }
    908973
    909974        int rc2 = RTCritSectLeave(&mWaitEventCritSect);
     
    911976            rc = rc2;
    912977    }
     978
     979    return rc;
    913980}
    914981
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