From 68e5673bb1ca080bbaf5cf7198fcf2deafa60772 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 24 Nov 2010 10:28:50 +0100 Subject: QThreadStorage: fix crash if thread local destructor reset himself Regression in ed8f3b6c98f1b305f0d183bc70c5f810a9c45ef2 (QTBUG-14579) WebKit ThreadSpecific implementation does that. See the comment in ThreadSpecific::destroy(void*) Reveiwed-by: Brad --- src/corelib/thread/qthreadstorage.cpp | 5 +++ tests/auto/qthreadstorage/tst_qthreadstorage.cpp | 44 ++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp index 07d940f..416fcfb 100644 --- a/src/corelib/thread/qthreadstorage.cpp +++ b/src/corelib/thread/qthreadstorage.cpp @@ -201,6 +201,11 @@ void QThreadStorageData::finish(void **p) continue; } destructor(q); //crash here might mean the thread exited after qthreadstorage was destroyed + + if (tls->size() > i) { + //re reset the tls in case it has been recreated by its own destructor. + (*tls)[i] = 0; + } } tls->clear(); } diff --git a/tests/auto/qthreadstorage/tst_qthreadstorage.cpp b/tests/auto/qthreadstorage/tst_qthreadstorage.cpp index 90e0311..0237dac 100644 --- a/tests/auto/qthreadstorage/tst_qthreadstorage.cpp +++ b/tests/auto/qthreadstorage/tst_qthreadstorage.cpp @@ -78,6 +78,7 @@ private slots: void ensureCleanupOrder(); void QTBUG13877_crashOnExit(); void QTBUG14579_leakInDestructor(); + void QTBUG14579_resetInDestructor(); void valueBased(); }; @@ -384,6 +385,49 @@ void tst_QThreadStorage::QTBUG14579_leakInDestructor() QCOMPARE(int(SPointer::count), c); } + +class QTBUG14579_reset; +Q_GLOBAL_STATIC(QThreadStorage, QTBUG14579_resetTls) + +class QTBUG14579_reset { +public: + SPointer member; + ~QTBUG14579_reset() { + //Quite stupid, but WTF::ThreadSpecific::destroy does it. + QTBUG14579_resetTls()->setLocalData(this); + } +}; + + +void tst_QThreadStorage::QTBUG14579_resetInDestructor() +{ + class Thread : public QThread + { + public: + void run() + { + QVERIFY(!QTBUG14579_resetTls()->hasLocalData()); + QTBUG14579_resetTls()->setLocalData(new QTBUG14579_reset); + QVERIFY(QTBUG14579_resetTls()->hasLocalData()); + } + }; + int c = SPointer::count; + + Thread t1; + Thread t2; + Thread t3; + t1.start(); + t2.start(); + t3.start(); + QVERIFY(t1.wait()); + QVERIFY(t2.wait()); + QVERIFY(t3.wait()); + + //check all the constructed things have been destructed + QCOMPARE(int(SPointer::count), c); +} + + void tst_QThreadStorage::valueBased() { struct Thread : QThread { -- cgit v0.12