From 950b35cf97ad398f97883efd2a18ee97994a8a9c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 18 Jan 2013 14:39:00 +0800 Subject: Clear the current thread data for the main thread This avoids crashes accessing deleted memory when creating a QObject after the last QObject had been deleted, like a qDebug() in global destructors. ==41000== Invalid read of size 4 ==41000== at 0x5F01ED5: bool QBasicAtomicOps<4>::ref(int&) (qatomic_x86.h:208) ==41000== by 0x5F01309: QBasicAtomicInteger::ref() (qbasicatomic.h:147) ==41000== by 0x5F24051: QThreadData::ref() (qthread.cpp:100) ==41000== by 0x614A984: QObject::QObject(QObject*) (qobject.cpp:681) ==41000== Address 0x6ee73f0 is 0 bytes inside a block of size 152 free'd ==41000== at 0x4A0736C: operator delete(void*) (vg_replace_malloc.c:480) ==41000== by 0x5F240BF: QThreadData::deref() (qthread.cpp:109) ==41000== by 0x6113F6B: QCoreApplicationData::~QCoreApplicationData() (qcoreapplication.cpp:268) The comment right above the change in qthread.cpp looks eerily similar to the problem I'm trying to fix. However, the actual change that introduced the change is not in the Qt public history, so we can't know for sure what the problem was then. Change-Id: I0dba895b041fe6cf81e6f8939ca85035cd00aad1 Reviewed-by: Olivier Goffart --- src/corelib/kernel/qcoreapplication.cpp | 7 ------- src/corelib/thread/qthread.cpp | 1 + src/corelib/thread/qthread_p.h | 1 + src/corelib/thread/qthread_unix.cpp | 5 +++++ src/corelib/thread/qthread_win.cpp | 5 +++++ 5 files changed, 12 insertions(+), 7 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 1696aeb77b..46de52ec9f 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -300,13 +300,6 @@ struct QCoreApplicationData { #ifndef QT_NO_LIBRARY delete app_libpaths; #endif - - // cleanup the QAdoptedThread created for the main() thread - if (QCoreApplicationPrivate::theMainThread) { - QThreadData *data = QThreadData::get2(QCoreApplicationPrivate::theMainThread); - QCoreApplicationPrivate::theMainThread = 0; - data->deref(); // deletes the data and the adopted thread - } } #ifdef Q_OS_BLACKBERRY diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index bd8c6341c1..79199c97e0 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -76,6 +76,7 @@ QThreadData::~QThreadData() // the problem... if (this->thread == QCoreApplicationPrivate::theMainThread) { QCoreApplicationPrivate::theMainThread = 0; + QThreadData::clearCurrentThreadData(); } QThread *t = thread; diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 526633cafa..2cf988260f 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -223,6 +223,7 @@ public: ~QThreadData(); static QThreadData *current(); + static void clearCurrentThreadData(); static QThreadData *get2(QThread *thread) { Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; } diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 8104cc8938..44ad8d3ac2 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -204,6 +204,11 @@ static void clear_thread_data() pthread_setspecific(current_thread_data_key, 0); } +void QThreadData::clearCurrentThreadData() +{ + clear_thread_data(); +} + QThreadData *QThreadData::current() { QThreadData *data = get_thread_data(); diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 8614330d6f..0cf903bb3a 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -96,6 +96,11 @@ Q_DESTRUCTOR_FUNCTION(qt_free_tls) /* QThreadData */ +void QThreadData::clearCurrentThreadData() +{ + TlsSetValue(qt_current_thread_data_tls_index, 0); +} + QThreadData *QThreadData::current() { qt_create_tls(); -- cgit v1.2.3