SignalDumper: protect access to ignoreClasses

It's a shared list that, in theory, can be written to by multiple
threads. Protect it with a mutex.

To make the change in a clean way, move all the .contains() checks
into a separate function so we can simply hold the lock in there.

Pick-to: 6.6 6.5
Change-Id: I99ff185346d52e43a3f59f2910a7b2fa6031e3e4
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
(cherry picked from commit c60db318836cf22b0f00b78ea189ba33fcf7b1c7)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Mårten Nordheim 2023-10-13 13:41:16 +02:00 committed by Qt Cherry-pick Bot
parent d7c17432fe
commit a338e222cc

View File

@ -24,10 +24,21 @@ inline static void qPrintMessage(const QByteArray &ba)
}
Q_GLOBAL_STATIC(QList<QByteArray>, ignoreClasses)
Q_CONSTINIT static QBasicMutex ignoreClassesMutex;
Q_CONSTINIT thread_local int iLevel = 0;
Q_CONSTINIT thread_local int ignoreLevel = 0;
enum { IndentSpacesCount = 4 };
static bool classIsIgnored(const char *className)
{
if (Q_LIKELY(!ignoreClasses.exists()))
return false;
QMutexLocker locker(&ignoreClassesMutex);
if (ignoreClasses()->isEmpty())
return false;
return ignoreClasses()->contains(QByteArrayView(className));
}
static void qSignalDumperCallback(QObject *caller, int signal_index, void **argv)
{
Q_ASSERT(caller);
@ -38,7 +49,7 @@ static void qSignalDumperCallback(QObject *caller, int signal_index, void **argv
QMetaMethod member = QMetaObjectPrivate::signal(mo, signal_index);
Q_ASSERT(member.isValid());
if (QTest::ignoreClasses() && QTest::ignoreClasses()->contains(mo->className())) {
if (classIsIgnored(mo->className())) {
++QTest::ignoreLevel;
return;
}
@ -98,8 +109,7 @@ static void qSignalDumperCallbackSlot(QObject *caller, int method_index, void **
if (!member.isValid())
return;
if (QTest::ignoreLevel ||
(QTest::ignoreClasses() && QTest::ignoreClasses()->contains(mo->className())))
if (QTest::ignoreLevel || classIsIgnored(mo->className()))
return;
QByteArray str;
@ -122,8 +132,7 @@ static void qSignalDumperCallbackSlot(QObject *caller, int method_index, void **
static void qSignalDumperCallbackEndSignal(QObject *caller, int /*signal_index*/)
{
Q_ASSERT(caller); Q_ASSERT(caller->metaObject());
if (QTest::ignoreClasses()
&& QTest::ignoreClasses()->contains(caller->metaObject()->className())) {
if (classIsIgnored(caller->metaObject()->className())) {
--QTest::ignoreLevel;
Q_ASSERT(QTest::ignoreLevel >= 0);
return;
@ -156,13 +165,15 @@ void QSignalDumper::endDump()
void QSignalDumper::ignoreClass(const QByteArray &klass)
{
QMutexLocker locker(&QTest::ignoreClassesMutex);
if (QTest::ignoreClasses())
QTest::ignoreClasses()->append(klass);
}
void QSignalDumper::clearIgnoredClasses()
{
if (QTest::ignoreClasses())
QMutexLocker locker(&QTest::ignoreClassesMutex);
if (QTest::ignoreClasses.exists())
QTest::ignoreClasses()->clear();
}