diff options
authorThiago Macieira <>2017-10-16 22:31:42 -0700
committerFriedemann Kleint <>2017-10-27 20:00:27 +0000
commitcf2220385506fe9f94ef1dbfa43518e489e04155 (patch)
parentefb1a13282ec0d09326b0550df67b7b8e7e9a31e (diff)
Add a comment about the weird refcount for adopted QThreadData
It's perfectly benign, but I spent a lot of time debugging this and trying to figure out how to solve something that didn't need solving. So document for posterity. For an adopted thread, the TLS destructors or the adopted thread watcher on Windows will call QThreadData::deref(): - QThreadData::deref(), count drops to zero -> delete this; - ~QThreadData() deletes the QAdoptedThread -> delete t; - ~QThreadPrivate() calls deref() again -> data->deref(); - QThreadData::deref(), count drops to -1, no action taken - ~QObjectPrivate() calls deref() yet again -> threadData->deref() - QThreadData::deref(), count drops to -2, no action taken Change-Id: Icaa86fc7b54d4b368c0efffd14ee448e0796e8d7 Reviewed-by: Friedemann Kleint <> Reviewed-by: Thiago Macieira <>
1 files changed, 7 insertions, 0 deletions
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index e92be64dfa..cad7a14017 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -78,6 +78,13 @@ QThreadData::~QThreadData()
+ // ~QThread() sets thread to nullptr, so if it isn't null here, it's
+ // because we're being run before the main object itself. This can only
+ // happen for QAdoptedThread. Note that both ~QThreadPrivate() and
+ // ~QObjectPrivate() will deref this object again, but that is acceptable
+ // because this destructor is still running (the _ref sub-object has not
+ // been destroyed) and there's no reentrancy. The refcount will become
+ // negative, but that's acceptable.
QThread *t = thread;
thread = 0;
delete t;