From 5b62a5e7aabcc818408f2fe28b9760082f474def Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Thu, 19 Nov 2015 13:12:41 +0200 Subject: [PATCH] Fix deadlock when setting environment variables. Qt uses QHash as the container for faking environment variables on Windows Runtime and CE. Environment variable manipulation functions are protected by mutex. Accessing the QT_HASH_SEED environment variable inside QHash can lead to situation where qputenv() call leads to qgetenv() call and that leads to a deadlock. Since the application environment is faked anyway, drop support for QT_HASH_SEED and ifdef that functionality out on those platforms. Documentation is updated to reflect changes. Task-number: QTBUG-49529 Change-Id: I1b1c28cb0b041fe2a63ca3dce57068fcb46505a7 Reviewed-by: Oswald Buddenhagen Reviewed-by: Andrew Knight --- src/corelib/tools/qhash.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index b334a697a9..fe49e8c6a8 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -38,6 +38,14 @@ #ifndef _CRT_RAND_S #define _CRT_RAND_S #endif + +// Windows Runtime and CE use a QHash to fake environment variables. To avoid +// deadlock, disable reading the QT_HASH_SEED environment variable within +// QHash. +#if defined(Q_OS_WINRT) || defined(Q_OS_WINCE) +# define QHASH_NO_ENV_SEED +#endif + #include #include "qhash.h" @@ -223,9 +231,11 @@ static uint qt_create_qhash_seed() uint seed = 0; #ifndef QT_BOOTSTRAPPED +#ifdef QHASH_NO_ENV_SEED QByteArray envSeed = qgetenv("QT_HASH_SEED"); if (!envSeed.isNull()) return envSeed.toUInt(); +#endif // QHASH_NO_ENV_SEED #ifdef Q_OS_UNIX int randomfd = qt_safe_open("/dev/urandom", O_RDONLY); @@ -327,8 +337,10 @@ int qGlobalQHashSeed() */ void qSetGlobalQHashSeed(int newSeed) { +#ifdef QHASH_NO_ENV_SEED if (qEnvironmentVariableIsSet("QT_HASH_SEED")) return; +#endif // QHASH_NO_ENV_SEED if (newSeed == -1) { int x(qt_create_qhash_seed() & INT_MAX); qt_qhash_seed.store(x); @@ -1182,6 +1194,9 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW decimal value, will be used as the seed for qHash(). Alternatively, you can call the qSetGlobalQHashSeed() function. + \note The environment variable \c QT_HASH_SEED is unsupported on Windows + Runtime and CE. Use qSetGlobalQHashSeed() instead on those platforms. + \sa QHashIterator, QMutableHashIterator, QMap, QSet */