summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmytro Poplavskiy <dmytro.poplavskiy@nokia.com>2009-11-03 02:47:48 (GMT)
committerDmytro Poplavskiy <dmytro.poplavskiy@nokia.com>2009-11-03 02:47:48 (GMT)
commitf72c2d50b6ab7fc4a8ea3524e22de63ca8a366f7 (patch)
treeeabeb0d99d8a9ec94aecaf08ea89ff21977f0112
parent5fc1013753babd397efbe5b7bae0dac387fbc2fd (diff)
downloadQt-f72c2d50b6ab7fc4a8ea3524e22de63ca8a366f7.zip
Qt-f72c2d50b6ab7fc4a8ea3524e22de63ca8a366f7.tar.gz
Qt-f72c2d50b6ab7fc4a8ea3524e22de63ca8a366f7.tar.bz2
Fixed qrand global static related problem.
qrand() uses global static seed storage, but if used from destructors of other global static objects (directly or via ~QSettings() or QMap::insert()) the global static seed storage can be already deleted. Fallback to plain rand() in this case. Task-number: QTBUG-5218 Reviewed-by: Justin McPherson
-rw-r--r--src/corelib/global/qglobal.cpp59
1 files changed, 40 insertions, 19 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 7d47944..36e15b9 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2513,10 +2513,19 @@ Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value
void qsrand(uint seed)
{
#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && !defined(Q_OS_SYMBIAN)
- SeedStorageType *pseed = randTLS()->localData();
- if (!pseed)
- randTLS()->setLocalData(pseed = new SeedStorageType);
- *pseed = seed;
+ SeedStorage *seedStorage = randTLS();
+ if (seedStorage) {
+ SeedStorageType *pseed = seedStorage->localData();
+ if (!pseed)
+ seedStorage->setLocalData(pseed = new SeedStorageType);
+ *pseed = seed;
+ } else {
+ //golbal static seed storage should always exist,
+ //except after being deleted by QGlobalStaticDeleter.
+ //But since it still can be called from destructor of another
+ //global static object, fallback to sqrand(seed)
+ srand(seed);
+ }
#else
// On Windows srand() and rand() already use Thread-Local-Storage
// to store the seed between calls
@@ -2536,17 +2545,20 @@ void qsrand(uint seed)
void qsrand()
{
#if (defined(Q_OS_UNIX) || defined(Q_OS_WIN)) && !defined(QT_NO_THREAD) && !defined(Q_OS_SYMBIAN)
- SeedStorageType *pseed = randTLS()->localData();
- if (pseed) {
- // already seeded
- return;
+ SeedStorage *seedStorage = randTLS();
+ if (seedStorage) {
+ SeedStorageType *pseed = seedStorage->localData();
+ if (pseed) {
+ // already seeded
+ return;
+ }
+ seedStorage->setLocalData(pseed = new SeedStorageType);
+ // start beyond 1 to avoid the sequence reset
+ static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(2);
+ *pseed = QDateTime::currentDateTime().toTime_t()
+ + quintptr(&pseed)
+ + serial.fetchAndAddRelaxed(1);
}
- randTLS()->setLocalData(pseed = new SeedStorageType);
- // start beyond 1 to avoid the sequence reset
- static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(2);
- *pseed = QDateTime::currentDateTime().toTime_t()
- + quintptr(&pseed)
- + serial.fetchAndAddRelaxed(1);
#if defined(Q_OS_WIN)
// for Windows the srand function must still be called.
srand(*pseed);
@@ -2584,12 +2596,21 @@ void qsrand()
int qrand()
{
#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && !defined(Q_OS_SYMBIAN)
- SeedStorageType *pseed = randTLS()->localData();
- if (!pseed) {
- randTLS()->setLocalData(pseed = new SeedStorageType);
- *pseed = 1;
+ SeedStorage *seedStorage = randTLS();
+ if (seedStorage) {
+ SeedStorageType *pseed = seedStorage->localData();
+ if (!pseed) {
+ seedStorage->setLocalData(pseed = new SeedStorageType);
+ *pseed = 1;
+ }
+ return rand_r(pseed);
+ } else {
+ //golbal static seed storage should always exist,
+ //except after being deleted by QGlobalStaticDeleter.
+ //But since it still can be called from destructor of another
+ //global static object, fallback to qrand()
+ return rand();
}
- return rand_r(pseed);
#else
// On Windows srand() and rand() already use Thread-Local-Storage
// to store the seed between calls