Add a way to access QCoreApplication's instance atomically
We use it from many places in Qt that may run before QCoreApplication has been created (officially not supported but it happens) and after it has been destroyed. In particular, we have code in QtDBus that runs in another thread after QCoreApplication has been destroyed and uses the event system. Accessing QCoreApplication::self anywhere but the main thread was a race condition in those conditions. Pick-to: 6.8 Change-Id: If4ad1af9301dca98ba69fffdf88c63b220db53ac Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
This commit is contained in:
parent
5ecbba1648
commit
7d92ecd917
@ -140,6 +140,11 @@ extern QString qAppFileName();
|
|||||||
|
|
||||||
Q_CONSTINIT bool QCoreApplicationPrivate::setuidAllowed = false;
|
Q_CONSTINIT bool QCoreApplicationPrivate::setuidAllowed = false;
|
||||||
|
|
||||||
|
Q_CONSTINIT QCoreApplication *QCoreApplication::self = nullptr;
|
||||||
|
Q_CONSTINIT static QBasicAtomicPointer<QCoreApplication> g_self = nullptr;
|
||||||
|
# undef qApp
|
||||||
|
# define qApp g_self.loadRelaxed()
|
||||||
|
|
||||||
#if !defined(Q_OS_WIN)
|
#if !defined(Q_OS_WIN)
|
||||||
#ifdef Q_OS_DARWIN
|
#ifdef Q_OS_DARWIN
|
||||||
QString QCoreApplicationPrivate::infoDictionaryStringProperty(const QString &propertyName)
|
QString QCoreApplicationPrivate::infoDictionaryStringProperty(const QString &propertyName)
|
||||||
@ -199,7 +204,7 @@ Q_CONSTINIT QString *QCoreApplicationPrivate::cachedApplicationFilePath = nullpt
|
|||||||
|
|
||||||
bool QCoreApplicationPrivate::checkInstance(const char *function)
|
bool QCoreApplicationPrivate::checkInstance(const char *function)
|
||||||
{
|
{
|
||||||
bool b = (QCoreApplication::self != nullptr);
|
bool b = (qApp != nullptr);
|
||||||
if (!b)
|
if (!b)
|
||||||
qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
|
qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
|
||||||
return b;
|
return b;
|
||||||
@ -359,7 +364,6 @@ Q_CONSTINIT QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher =
|
|||||||
|
|
||||||
#endif // QT_NO_QOBJECT
|
#endif // QT_NO_QOBJECT
|
||||||
|
|
||||||
Q_CONSTINIT QCoreApplication *QCoreApplication::self = nullptr;
|
|
||||||
Q_CONSTINIT uint QCoreApplicationPrivate::attribs =
|
Q_CONSTINIT uint QCoreApplicationPrivate::attribs =
|
||||||
(1 << Qt::AA_SynthesizeMouseForUnhandledTouchEvents) |
|
(1 << Qt::AA_SynthesizeMouseForUnhandledTouchEvents) |
|
||||||
(1 << Qt::AA_SynthesizeMouseForUnhandledTabletEvents);
|
(1 << Qt::AA_SynthesizeMouseForUnhandledTabletEvents);
|
||||||
@ -817,6 +821,7 @@ void Q_TRACE_INSTRUMENT(qtcore) QCoreApplicationPrivate::init()
|
|||||||
|
|
||||||
Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
|
Q_ASSERT_X(!QCoreApplication::self, "QCoreApplication", "there should be only one application object");
|
||||||
QCoreApplication::self = q;
|
QCoreApplication::self = q;
|
||||||
|
g_self.storeRelaxed(q);
|
||||||
|
|
||||||
#if QT_CONFIG(thread)
|
#if QT_CONFIG(thread)
|
||||||
#ifdef Q_OS_WASM
|
#ifdef Q_OS_WASM
|
||||||
@ -918,6 +923,7 @@ QCoreApplication::~QCoreApplication()
|
|||||||
qt_call_post_routines();
|
qt_call_post_routines();
|
||||||
|
|
||||||
self = nullptr;
|
self = nullptr;
|
||||||
|
g_self.storeRelaxed(nullptr);
|
||||||
#ifndef QT_NO_QOBJECT
|
#ifndef QT_NO_QOBJECT
|
||||||
QCoreApplicationPrivate::is_app_closing = true;
|
QCoreApplicationPrivate::is_app_closing = true;
|
||||||
QCoreApplicationPrivate::is_app_running = false;
|
QCoreApplicationPrivate::is_app_running = false;
|
||||||
@ -1096,7 +1102,7 @@ void QCoreApplication::setQuitLockEnabled(bool enabled)
|
|||||||
bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
|
bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
|
||||||
{
|
{
|
||||||
bool selfRequired = QCoreApplicationPrivate::threadRequiresCoreApplication();
|
bool selfRequired = QCoreApplicationPrivate::threadRequiresCoreApplication();
|
||||||
if (selfRequired && !self)
|
if (selfRequired && !qApp)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Make it possible for Qt Script to hook into events even
|
// Make it possible for Qt Script to hook into events even
|
||||||
@ -1121,7 +1127,7 @@ bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
|
|||||||
if (threadData->thread.loadRelaxed() != QCoreApplicationPrivate::mainThread())
|
if (threadData->thread.loadRelaxed() != QCoreApplicationPrivate::mainThread())
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
return self->notify(receiver, event);
|
return qApp->notify(receiver, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1250,7 +1256,7 @@ bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiv
|
|||||||
bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, QEvent *event)
|
bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, QEvent *event)
|
||||||
{
|
{
|
||||||
if ((receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() != mainThread()
|
if ((receiver->d_func()->threadData.loadRelaxed()->thread.loadAcquire() != mainThread()
|
||||||
|| receiver != QCoreApplication::instance())
|
|| receiver != qApp)
|
||||||
&& receiver->d_func()->extraData) {
|
&& receiver->d_func()->extraData) {
|
||||||
for (qsizetype i = 0; i < receiver->d_func()->extraData->eventFilters.size(); ++i) {
|
for (qsizetype i = 0; i < receiver->d_func()->extraData->eventFilters.size(); ++i) {
|
||||||
QObject *obj = receiver->d_func()->extraData->eventFilters.at(i);
|
QObject *obj = receiver->d_func()->extraData->eventFilters.at(i);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user