diff options
author | Alex Trotsenko <alex1973tr@gmail.com> | 2019-11-16 16:02:29 +0200 |
---|---|---|
committer | Alex Trotsenko <alex1973tr@gmail.com> | 2020-03-03 19:44:01 +0200 |
commit | 23785face5a01bf63334fd32975718468d5f816e (patch) | |
tree | cfdea28f388edfd2c994fe62dc350f191c71be95 | |
parent | b711ee255515440b923a898f65f6afe13d63916f (diff) |
QEventDispatcherWin32: unregister event notifiers on close
When QEventDispatcherWin32::closingDown() is called,
threadData->eventDispatcher is already nullptr and the application
will no longer process the events.
Thus, just as it works for socket notifiers and timers, it makes sense
to disable all active event notifiers at this point. Otherwise, it
seems possible that an object in signalled state can provoke a data
race in the notifier's callback on 'edp' pointer, if
QWin32EventDispatcher destructor is running simultaneously.
Task-number: QTBUG-64152
Task-number: QTBUG-70214
Change-Id: I6e77f3eeca1b0ea639021e73b86798cba0200ebf
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win.cpp | 8 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_win_p.h | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qwineventnotifier.cpp | 5 |
3 files changed, 10 insertions, 4 deletions
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 8616631603..f2216d4113 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -884,7 +884,11 @@ void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier) return; } #endif + doUnregisterEventNotifier(notifier); +} +void QEventDispatcherWin32::doUnregisterEventNotifier(QWinEventNotifier *notifier) +{ Q_D(QEventDispatcherWin32); int i = d->winEventNotifierList.indexOf(notifier); @@ -996,6 +1000,10 @@ void QEventDispatcherWin32::closingDown() doUnregisterSocketNotifier((*(d->sn_except.begin()))->obj); Q_ASSERT(d->active_fd.isEmpty()); + // clean up any eventnotifiers + while (!d->winEventNotifierList.isEmpty()) + doUnregisterEventNotifier(d->winEventNotifierList.first()); + // clean up any timers for (int i = 0; i < d->timerVec.count(); ++i) d->unregisterTimer(d->timerVec.at(i)); diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index e6620178d8..a482c8b7db 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -110,6 +110,7 @@ protected: QEventDispatcherWin32(QEventDispatcherWin32Private &dd, QObject *parent = 0); virtual void sendPostedEvents(); void doUnregisterSocketNotifier(QSocketNotifier *notifier); + void doUnregisterEventNotifier(QWinEventNotifier *notifier); private: friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp); diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp index db5d44b276..0c574e9a4b 100644 --- a/src/corelib/kernel/qwineventnotifier.cpp +++ b/src/corelib/kernel/qwineventnotifier.cpp @@ -198,11 +198,8 @@ void QWinEventNotifier::setEnabled(bool enable) d->enabled = enable; QAbstractEventDispatcher *eventDispatcher = d->threadData.loadRelaxed()->eventDispatcher.loadRelaxed(); - if (!eventDispatcher) { // perhaps application is shutting down - if (!enable && d->waitHandle != nullptr) - d->unregisterWaitObject(); + if (!eventDispatcher) // perhaps application is shutting down return; - } if (Q_UNLIKELY(thread() != QThread::currentThread())) { qWarning("QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread"); return; |