summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qtenvironmentvariables.cpp
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2023-02-02 13:54:13 +0100
committerEdward Welbourne <edward.welbourne@qt.io>2023-02-03 14:45:31 +0100
commitb62ac40987e4a53be912227230c4914e77c74e88 (patch)
tree7ce6679ad4cda94f5fac9f7e005593586192f9f0 /src/corelib/global/qtenvironmentvariables.cpp
parent9d1a3582f33a0820a4f0f5b7fe84a22a8c8d967b (diff)
Move qtLocalTime() to qtenvironmentvariables.cpp as qLocalTime()
The new name better matches the names of existing functions there. A comment on the old code noted that such a move should really be done, so as to correctly share the environment-mutex locking. In the process, move the (now three) time-related internal functions from qglobal_p.h to a new qtenvironmentvariables_p.h since that's the natural place for them given where they're defined (and the fact that they're for internal use only). Change-Id: Ib028baebaf31a806a2c0c97caaaba0a466c11cea Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/global/qtenvironmentvariables.cpp')
-rw-r--r--src/corelib/global/qtenvironmentvariables.cpp50
1 files changed, 44 insertions, 6 deletions
diff --git a/src/corelib/global/qtenvironmentvariables.cpp b/src/corelib/global/qtenvironmentvariables.cpp
index 4046beae1f4..4f2a263cc43 100644
--- a/src/corelib/global/qtenvironmentvariables.cpp
+++ b/src/corelib/global/qtenvironmentvariables.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qtenvironmentvariables.h"
+#include "qtenvironmentvariables_p.h"
#include <qplatformdefs.h>
#include <QtCore/qbytearray.h>
@@ -330,9 +331,11 @@ bool qunsetenv(const char *varName)
#endif
}
-/*
- Wraps tzset(), which accesses the environment, so should only be called while
- we hold the lock on the environment mutex.
+/* Various time-related APIs that need to consult system settings also need
+ protection with the same lock as the environment, since those system settings
+ include part of the environment (principally TZ).
+
+ First, tzset(), which POSIX explicitly says accesses the environment.
*/
void qTzSet()
{
@@ -344,9 +347,8 @@ void qTzSet()
#endif // Q_OS_WIN
}
-/*
- Wrap mktime(), which is specified to behave as if it called tzset(), hence
- shares its implicit environment-dependence.
+/* Wrap mktime(), which is specified to behave as if it called tzset(), hence
+ shares its implicit environment-dependence.
*/
time_t qMkTime(struct tm *when)
{
@@ -354,4 +356,40 @@ time_t qMkTime(struct tm *when)
return mktime(when);
}
+/* For localtime(), POSIX mandates that it behave as if it called tzset().
+ For the alternatives to it, we need (if only for compatibility) to do the
+ same explicitly, which should ensure a re-parse of timezone info.
+*/
+bool qLocalTime(time_t utc, struct tm *local)
+{
+ const auto locker = qt_scoped_lock(environmentMutex);
+#if defined(Q_OS_WIN)
+ // The doc of localtime_s() says that it corrects for the same things
+ // _tzset() sets the globals for, but QTBUG-109974 reveals a need for an
+ // explicit call, all the same.
+ _tzset();
+ return !localtime_s(local, &utc);
+#elif QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+ // Use the reentrant version of localtime() where available, as it is
+ // thread-safe and doesn't use a shared static data area.
+ // As localtime_r() is not specified to work as if it called tzset(),
+ // make an explicit call.
+ tzset();
+ if (tm *res = localtime_r(&utc, local)) {
+ Q_ASSERT(res == local);
+ return true;
+ }
+ return false;
+#else
+ // POSIX mandates that localtime() behaves as if it called tzset().
+ // Returns shared static data which may be overwritten at any time (albeit
+ // our lock probably keeps it safe). So copy the result promptly:
+ if (tm *res = localtime(&utc)) {
+ *local = *res;
+ return true;
+ }
+ return false;
+#endif
+}
+
QT_END_NAMESPACE