diff options
author | David Faure <david.faure@kdab.com> | 2014-06-08 21:46:24 +0200 |
---|---|---|
committer | Thiago Macieira <thiago.macieira@intel.com> | 2014-06-20 21:54:04 +0200 |
commit | 884b38157689a893ace0a4c793fab921167abb2c (patch) | |
tree | c0f4a079a79c760ad08506017ed296880f529da1 /src/corelib/io | |
parent | d98004cd2f33e8147cff9f3cb203fdef5e6dd00e (diff) |
Fix data race on QLoggingCategory when using qDebug from multiple threads
setEnabled() would race with isEnabled()/isDebugEnabled()/etc.
Change-Id: I2004cba81d5417a634b97f5c2f98d3a4ab71770d
Reviewed-by: David Faure <david.faure@kdab.com>
Diffstat (limited to 'src/corelib/io')
-rw-r--r-- | src/corelib/io/qloggingcategory.cpp | 36 | ||||
-rw-r--r-- | src/corelib/io/qloggingcategory.h | 35 |
2 files changed, 53 insertions, 18 deletions
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index 518052e537..45fab11939 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -50,6 +50,18 @@ const char qtDefaultCategoryName[] = "default"; Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory, (qtDefaultCategoryName)) +#ifndef Q_ATOMIC_INT8_IS_SUPPORTED +static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) +{ + const int bit = 1 << shift; + + if (enable) + atomic->fetchAndOrRelaxed(bit); + else + atomic->fetchAndAndRelaxed(~bit); +} +#endif + /*! \class QLoggingCategory \inmodule QtCore @@ -171,13 +183,11 @@ Q_GLOBAL_STATIC_WITH_ARGS(QLoggingCategory, qtDefaultCategory, */ QLoggingCategory::QLoggingCategory(const char *category) : d(0), - name(0), - enabledDebug(true), - enabledWarning(true), - enabledCritical(true) + name(0) { Q_UNUSED(d); Q_UNUSED(placeholder); + enabled.store(0x01010101); // enabledDebug = enabledWarning = enabledCritical = true; const bool isDefaultCategory = (category == 0) || (strcmp(category, qtDefaultCategoryName) == 0); @@ -249,9 +259,9 @@ QLoggingCategory::~QLoggingCategory() bool QLoggingCategory::isEnabled(QtMsgType msgtype) const { switch (msgtype) { - case QtDebugMsg: return enabledDebug; - case QtWarningMsg: return enabledWarning; - case QtCriticalMsg: return enabledCritical; + case QtDebugMsg: return isDebugEnabled(); + case QtWarningMsg: return isWarningEnabled(); + case QtCriticalMsg: return isCriticalEnabled(); case QtFatalMsg: return true; } return false; @@ -270,9 +280,15 @@ bool QLoggingCategory::isEnabled(QtMsgType msgtype) const void QLoggingCategory::setEnabled(QtMsgType type, bool enable) { switch (type) { - case QtDebugMsg: enabledDebug = enable; break; - case QtWarningMsg: enabledWarning = enable; break; - case QtCriticalMsg: enabledCritical = enable; break; +#ifdef Q_ATOMIC_INT8_IS_SUPPORTED + case QtDebugMsg: bools.enabledDebug.store(enable); break; + case QtWarningMsg: bools.enabledWarning.store(enable); break; + case QtCriticalMsg: bools.enabledCritical.store(enable); break; +#else + case QtDebugMsg: setBoolLane(&enabled, enable, DebugShift); break; + case QtWarningMsg: setBoolLane(&enabled, enable, WarningShift); break; + case QtCriticalMsg: setBoolLane(&enabled, enable, CriticalShift); break; +#endif case QtFatalMsg: break; } } diff --git a/src/corelib/io/qloggingcategory.h b/src/corelib/io/qloggingcategory.h index 4aec8e63bf..573af2105c 100644 --- a/src/corelib/io/qloggingcategory.h +++ b/src/corelib/io/qloggingcategory.h @@ -57,10 +57,15 @@ public: bool isEnabled(QtMsgType type) const; void setEnabled(QtMsgType type, bool enable); - bool isDebugEnabled() const { return enabledDebug; } - bool isWarningEnabled() const { return enabledWarning; } - bool isCriticalEnabled() const { return enabledCritical; } - +#ifdef Q_ATOMIC_INT8_IS_SUPPORTED + bool isDebugEnabled() const { return bools.enabledDebug.load(); } + bool isWarningEnabled() const { return bools.enabledWarning.load(); } + bool isCriticalEnabled() const { return bools.enabledCritical.load(); } +#else + bool isDebugEnabled() const { return enabled.load() >> DebugShift & 1; } + bool isWarningEnabled() const { return enabled.load() >> WarningShift & 1; } + bool isCriticalEnabled() const { return enabled.load() >> CriticalShift & 1; } +#endif const char *categoryName() const { return name; } // allows usage of both factory method and variable in qCX macros @@ -78,10 +83,24 @@ private: void *d; // reserved for future use const char *name; - bool enabledDebug; - bool enabledWarning; - bool enabledCritical; - bool placeholder[5]; // reserve for future use +#ifdef Q_BIG_ENDIAN + enum { DebugShift = 0, WarningShift = 8, CriticalShift = 16 }; +#else + enum { DebugShift = 24, WarningShift = 16, CriticalShift = 8 }; +#endif + + struct AtomicBools { +#ifdef Q_ATOMIC_INT8_IS_SUPPORTED + QBasicAtomicInteger<bool> enabledDebug; + QBasicAtomicInteger<bool> enabledWarning; + QBasicAtomicInteger<bool> enabledCritical; +#endif + }; + union { + AtomicBools bools; + QBasicAtomicInt enabled; + }; + bool placeholder[4]; // reserve for future use }; #define Q_DECLARE_LOGGING_CATEGORY(name) \ |