summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Goffart <olivier.goffart@nokia.com>2010-11-24 09:28:50 (GMT)
committerOlivier Goffart <olivier.goffart@nokia.com>2010-11-24 15:02:29 (GMT)
commit68e5673bb1ca080bbaf5cf7198fcf2deafa60772 (patch)
tree11e0fb9b40a6437d227681411257c8d1b06a6409
parent7d11b50933ad6cfaebda1190d8d8b9ba470c8013 (diff)
downloadQt-68e5673bb1ca080bbaf5cf7198fcf2deafa60772.zip
Qt-68e5673bb1ca080bbaf5cf7198fcf2deafa60772.tar.gz
Qt-68e5673bb1ca080bbaf5cf7198fcf2deafa60772.tar.bz2
QThreadStorage: fix crash if thread local destructor reset himself
Regression in ed8f3b6c98f1b305f0d183bc70c5f810a9c45ef2 (QTBUG-14579) WebKit ThreadSpecific implementation does that. See the comment in ThreadSpecific<T>::destroy(void*) Reveiwed-by: Brad
-rw-r--r--src/corelib/thread/qthreadstorage.cpp5
-rw-r--r--tests/auto/qthreadstorage/tst_qthreadstorage.cpp44
2 files changed, 49 insertions, 0 deletions
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_reset *>, QTBUG14579_resetTls)
+
+class QTBUG14579_reset {
+public:
+ SPointer member;
+ ~QTBUG14579_reset() {
+ //Quite stupid, but WTF::ThreadSpecific<T>::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 {