summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel/qfunctions_fake_env_p.h
diff options
context:
space:
mode:
authorSamuel Nevala <samuel.nevala@intopalo.com>2015-12-07 10:51:18 +0200
committerMaurice Kalinowski <maurice.kalinowski@theqtcompany.com>2016-01-04 13:12:19 +0000
commit7fdfaad43f75bab9d701b0b55c13570d2140fde4 (patch)
tree10bc02371bd08ae125ee67290a7b10a7cd250b1d /src/corelib/kernel/qfunctions_fake_env_p.h
parentb12e876efce4309ed61c04b9232ee80ec64baddc (diff)
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. Change the container from QHash to QVector to avoid deadlock. Task-number: QTBUG-49529 Change-Id: I550ead4ab12e7abebc044f52339063a44fcf0170 Reviewed-by: Marc Mutz <marc.mutz@kdab.com> Reviewed-by: Maurice Kalinowski <maurice.kalinowski@theqtcompany.com>
Diffstat (limited to 'src/corelib/kernel/qfunctions_fake_env_p.h')
-rw-r--r--src/corelib/kernel/qfunctions_fake_env_p.h51
1 files changed, 36 insertions, 15 deletions
diff --git a/src/corelib/kernel/qfunctions_fake_env_p.h b/src/corelib/kernel/qfunctions_fake_env_p.h
index 8b1ab44696..b4c5ffb079 100644
--- a/src/corelib/kernel/qfunctions_fake_env_p.h
+++ b/src/corelib/kernel/qfunctions_fake_env_p.h
@@ -46,51 +46,72 @@
//
#include "qbytearray.h"
-#include "qhash.h"
+#include "qvector.h"
QT_BEGIN_NAMESPACE
// Environment ------------------------------------------------------
-Q_CORE_EXPORT QHash<QByteArray, QByteArray> &qt_app_environment()
-{
- static QHash<QByteArray, QByteArray> internalEnvironment;
- return internalEnvironment;
-}
+struct Variable {
+ Variable() { }
+
+ Variable(const QByteArray &name, const QByteArray &value)
+ : name(name), value(value) { }
+
+ QByteArray name;
+ QByteArray value;
+};
+
+Q_DECLARE_TYPEINFO(Variable, Q_MOVABLE_TYPE);
+
+struct NameEquals {
+ typedef bool result_type;
+ const char *name;
+ explicit NameEquals(const char *name) Q_DECL_NOTHROW : name(name) {}
+ result_type operator()(const Variable &other) const Q_DECL_NOTHROW
+ { return qstrcmp(other.name, name) == 0; }
+};
+
+Q_GLOBAL_STATIC(QVector<Variable>, qt_app_environment)
errno_t qt_fake_getenv_s(size_t *sizeNeeded, char *buffer, size_t bufferSize, const char *varName)
{
if (!sizeNeeded)
return EINVAL;
- QHash<QByteArray, QByteArray>::const_iterator iterator = qt_app_environment().constFind(varName);
- if (iterator == qt_app_environment().constEnd()) {
+ QVector<Variable>::const_iterator end = qt_app_environment->constEnd();
+ QVector<Variable>::const_iterator iterator = std::find_if(qt_app_environment->constBegin(),
+ end,
+ NameEquals(varName));
+ if (iterator == end) {
if (buffer)
buffer[0] = '\0';
return ENOENT;
}
- const int size = iterator->size() + 1;
+ const int size = iterator->value.size() + 1;
if (bufferSize < size_t(size)) {
*sizeNeeded = size;
return ERANGE;
}
- qstrcpy(buffer, iterator->constData());
+ qstrcpy(buffer, iterator->value.constData());
return 0;
}
errno_t qt_fake__putenv_s(const char *varName, const char *value)
{
- QHash<QByteArray, QByteArray>::iterator iterator = qt_app_environment().find(varName);
- QHash<QByteArray, QByteArray>::iterator end = qt_app_environment().end();
+ QVector<Variable>::iterator end = qt_app_environment->end();
+ QVector<Variable>::iterator iterator = std::find_if(qt_app_environment->begin(),
+ end,
+ NameEquals(varName));
if (!value || !*value) {
if (iterator != end)
- qt_app_environment().erase(iterator);
+ qt_app_environment->erase(iterator);
} else {
if (iterator == end)
- qt_app_environment()[varName] = QByteArray(value);
+ qt_app_environment->append(Variable(varName, value));
else
- (*iterator) = value;
+ iterator->value = value;
}
return 0;