diff options
author | Dmytro Poplavskiy <dmytro.poplavskiy@nokia.com> | 2009-11-03 02:47:48 (GMT) |
---|---|---|
committer | Dmytro Poplavskiy <dmytro.poplavskiy@nokia.com> | 2009-11-03 02:47:48 (GMT) |
commit | f72c2d50b6ab7fc4a8ea3524e22de63ca8a366f7 (patch) | |
tree | eabeb0d99d8a9ec94aecaf08ea89ff21977f0112 | |
parent | 5fc1013753babd397efbe5b7bae0dac387fbc2fd (diff) | |
download | Qt-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.cpp | 59 |
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 |