VirtualBox

Changeset 93188 in vbox for trunk/src


Ignore:
Timestamp:
Jan 11, 2022 9:28:09 PM (3 years ago)
Author:
vboxsync
Message:

Main/Event: defunct passive event listeners prevent subsequent vetoable
events from being processed bugref:10000

If a passive event listener has registered an interest in a vetoable
event and subsequently disappears then any later passive event listeners
which are interested in the same vetoable event won't ever see
IEvent::setProcessed() called. The most common scenario where this is
seen is when the VBox GUI crashes and restarts during the same VBoxSVC
instance after which any time an OnExtraDataCanChange event is
triggered, such as by clicking a VM's name, it incurs a three second
timeout where nothing can be done in the GUI during that time. The fix
removes OnExtraDataCanChange from the unresponsive passive event
listener's list of interested events after it times out the first time
which means that the annoying three seconds of GUI inactivity will only
be seen once.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/src-all/EventImpl.cpp

    r93115 r93188  
    229229    {
    230230        *aResult = FALSE;
     231        /*
     232         * If we timed out then one or more passive listeners didn't process this event
     233         * within the time limit most likely due to the listener no longer being alive (e.g.
     234         * the VirtualBox GUI crashed) so we flag this to our caller so it can remove this
     235         * event from the list of events the passive listener is interested in.  This avoids
     236         * incurring this timeout every time the event is fired.
     237         */
     238        if (vrc == VERR_TIMEOUT)
     239            return E_ABORT;
    231240    }
    232241
     
    11761185
    11771186    if (fWaitable)
     1187    {
    11781188        hrc = aEvent->WaitProcessed(aTimeout, aResult);
     1189
     1190        /*
     1191         * If a passive listener times out without processing a vetoable event then we
     1192         * remove that event from the list of events this listener is interested in.
     1193         */
     1194        if (!*aResult && hrc == E_ABORT && implies(VBoxEventType_Vetoable, evType))
     1195        {
     1196            AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
     1197
     1198            EventMapList &listeners = m->mEvMap[(int)evType - FirstEvent];
     1199            for (EventMapList::iterator it = listeners.begin();
     1200                 it != listeners.end();
     1201                 ++it)
     1202            {
     1203                RecordHolder<ListenerRecord> record(*it);
     1204                if (record.obj()->mQueue.size() != 0 && record.obj()->mQueue.back() == aEvent)
     1205                    m->mEvMap[(int)evType - FirstEvent].remove(record.obj());
     1206            }
     1207
     1208            PendingEventsMap::iterator pit = m->mPendingMap.find(aEvent);
     1209            if (pit != m->mPendingMap.end())
     1210                m->mPendingMap.erase(pit);
     1211
     1212            /*
     1213             * VBoxEventDesc::fire() requires TRUE to be returned so it can handle
     1214             * vetoable events.
     1215             */
     1216            return S_OK;
     1217        }
     1218    }
    11791219    else
    11801220        *aResult = TRUE;
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