summaryrefslogtreecommitdiffstats
path: root/src/corelib/io/qloggingregistry.cpp
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2025-02-08 14:33:27 -0800
committerThiago Macieira <thiago.macieira@intel.com>2025-03-31 17:04:13 -0400
commit4afd089612448ae13136e287ced134c71499cfec (patch)
tree0215f40365e84069243c55547fdf78508c3c148b /src/corelib/io/qloggingregistry.cpp
parent51c8c0695192677f821759b98f8ba6496df41fa7 (diff)
QLoggingCategory: make defaultCategory() truly a global static
We don't need two independent Q_GLOBAL_STATIC variables: one for the default category and the other for the logging registry. We can simply save one in the other. However, we can do better than even that. QLoggingCategory currently doesn't hold any allocated resources: the const char *name points to a static string and the void *d is always null. That means the constructor and destructor only serve to register and unregister the category with QLoggingRegistry, so we transfer that responsibility to QLoggingRegistry itself (the un-registering is implicit in the registry's own destruction). The benefit of this is that the default QLoggingCategory can never be found in a destroyed state, however late user code may be running after ::exit() was called. We have had a number of these issues of De-Initialization Order Fiasco, especially since the changes to QThreadData destruction timing. Pick-to: 6.9 Change-Id: I2b6ea597ac257837669afffde2684c7b44a42e92 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib/io/qloggingregistry.cpp')
-rw-r--r--src/corelib/io/qloggingregistry.cpp23
1 files changed, 22 insertions, 1 deletions
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index da8ed80ff16..ece58cfa87e 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -27,6 +27,7 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
Q_GLOBAL_STATIC(QLoggingRegistry, qtLoggingRegistry)
+alignas(QLoggingCategory) static unsigned char defaultLoggingCategory[sizeof(QLoggingCategory)];
/*!
\internal
@@ -227,6 +228,14 @@ void QLoggingSettingsParser::parseNextLine(QStringView line)
QLoggingRegistry::QLoggingRegistry()
: categoryFilter(defaultCategoryFilter)
{
+ using U = QLoggingCategory::UnregisteredInitialization;
+ Q_ASSERT_X(!self, "QLoggingRegistry", "Singleton recreated");
+ self = this;
+
+ // can't use std::construct_at here - private constructor
+ auto cat = new (defaultLoggingCategory) QLoggingCategory(U{}, defaultCategoryName);
+ categories.emplace(cat, QtDebugMsg);
+
#if defined(Q_OS_ANDROID)
// Unless QCoreApplication has been constructed we can't be sure that
// we are on Qt's main thread. If we did allow logging here, we would
@@ -424,6 +433,18 @@ QLoggingRegistry *QLoggingRegistry::instance()
return qtLoggingRegistry();
}
+QLoggingCategory *QLoggingRegistry::defaultCategory()
+{
+ // Initialize the defaultLoggingCategory global static, if necessary. Note
+ // how it remains initialized forever, even if the QLoggingRegistry
+ // instance() is destroyed.
+ instance();
+
+ // std::launder() to be on the safe side, but it's unnecessary because the
+ // object is never recreated.
+ return std::launder(reinterpret_cast<QLoggingCategory *>(defaultLoggingCategory));
+}
+
/*!
\internal
Updates category settings according to rules.
@@ -432,7 +453,7 @@ QLoggingRegistry *QLoggingRegistry::instance()
*/
void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat)
{
- const QLoggingRegistry *reg = QLoggingRegistry::instance();
+ const QLoggingRegistry *reg = self;
Q_ASSERT(reg->categories.contains(cat));
QtMsgType enableForLevel = reg->categories.value(cat);