summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason McDonald <jason.mcdonald@nokia.com>2010-07-18 03:29:17 (GMT)
committerJason McDonald <jason.mcdonald@nokia.com>2010-07-18 03:29:17 (GMT)
commitd8944b560a16db3805d6faadfaadbabe750c0cef (patch)
tree8f27e4b4d85307800e2a406482ab08a82775f239 /src
parent67eaa50ad5ae1543fd165ac6ce29accfcc428036 (diff)
downloadQt-d8944b560a16db3805d6faadfaadbabe750c0cef.zip
Qt-d8944b560a16db3805d6faadfaadbabe750c0cef.tar.gz
Qt-d8944b560a16db3805d6faadfaadbabe750c0cef.tar.bz2
QUUid::createUuid() should not generate identical sequences on UNIX
An unintended side-effect of commit 90a082c9076f35dcca092ade019891e92692710e is that if qrand() is used without being seeded first, then createUuid() would always generate the same sequence. This quite likely to happen considering the Qt does not actually seed the PRNG, but does use it in many places (we do not call qsrand(), but we do often call qrand()). Fix this by changing qrand() to calculate a seed, instead of defaulting to 1. This allows us to remove the qsrand() overload with no arguments, since qrand() will now seed automatically unless manually seeded by the programmer. Task-number: QTBUG-11213 Reviewed-by: thiago (manually cherry picked from commits 2ef8b92ececbf9d33d7c0b44f46c7c975fb0fdaa and a0fffeed6fceb8244328b649a3f6feb520493bc2) Conflicts: src/corelib/plugin/quuid.cpp
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qglobal.cpp49
-rw-r--r--src/corelib/plugin/quuid.cpp22
2 files changed, 16 insertions, 55 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 75a51ec..c956b85 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2606,55 +2606,6 @@ void qsrand(uint seed)
#endif
}
-/*! \internal
- \relates <QtGlobal>
- \since 4.6
-
- Seed the PRNG, but only if it has not already been seeded.
-
- The default seed is a combination of current time, a stack address and a
- serial counter (since thread stack addresses are re-used).
-*/
-void qsrand()
-{
-#if (defined(Q_OS_UNIX) || defined(Q_OS_WIN)) && !defined(QT_NO_THREAD)
- 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);
-#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
- // for Windows and Symbian the srand function must still be called.
- srand(*pseed);
-#endif
- }
-
-//QT_NO_THREAD implementations
-#else
- static unsigned int seed = 0;
-
- if (seed)
- return;
-
-#if defined(Q_OS_SYMBIAN)
- seed = Math::Random();
-#elif defined(Q_OS_WIN)
- seed = GetTickCount();
-#else
- seed = quintptr(&seed) + QDateTime::currentDateTime().toTime_t();
-#endif
- srand(seed);
-#endif // defined(Q_OS_UNIX) || defined(Q_OS_WIN)) && !defined(QT_NO_THREAD)
-}
-
/*!
\relates <QtGlobal>
\since 4.2
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
index 9332bbc..7858b33 100644
--- a/src/corelib/plugin/quuid.cpp
+++ b/src/corelib/plugin/quuid.cpp
@@ -578,11 +578,9 @@ QUuid QUuid::createUuid()
QT_BEGIN_INCLUDE_NAMESPACE
#include "qdatetime.h"
#include "qfile.h"
-#include "stdlib.h" // For srand/rand
+#include "qthreadstorage.h"
QT_END_INCLUDE_NAMESPACE
-extern void qsrand(); // in qglobal.cpp
-
QUuid QUuid::createUuid()
{
QUuid result;
@@ -600,12 +598,24 @@ QUuid QUuid::createUuid()
static const int intbits = sizeof(int)*8;
static int randbits = 0;
if (!randbits) {
+ int r = 0;
int max = RAND_MAX;
- do { ++randbits; } while ((max=max>>1));
+ do { ++r; } while ((max=max>>1));
+ randbits = r;
}
- // reseed, but only if not already seeded
- qsrand();
+ static QThreadStorage<int *> uuidseed;
+ if (!uuidseed.hasLocalData()) {
+ // Seed the PRNG once per thread with a combination of current time, a
+ // stack address and a serial counter (since thread stack addresses are
+ // re-used).
+ int *pseed = new int;
+ static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(2);
+ qsrand(*pseed = QDateTime::currentDateTime().toTime_t()
+ + quintptr(&pseed)
+ + serial.fetchAndAddRelaxed(1));
+ uuidseed.setLocalData(pseed);
+ }
int chunks = 16 / sizeof(uint);
while (chunks--) {