From: Bruno Haible <bruno@clisp.org>
To: bug-gnulib@gnu.org
Subject: Re: MT-unsafe time modules
Date: Fri, 09 Feb 2024 21:22:12 +0100 [thread overview]
Message-ID: <2118215.VsPgYW4pTa@nimes> (raw)
In-Reply-To: <3755090.VQhiAETyHQ@nimes>
This patch makes ctime, localtime, tzset, wcsftime multithread-safe.
2024-02-09 Bruno Haible <bruno@clisp.org>
ctime, localtime, tzset, wcsftime: Make multithread-safe.
* lib/ctime.c: Include <wchar.h>.
(rpl_ctime): Modify _environ and _wenviron without using _putenv.
* lib/localtime.c: Include <wchar.h>.
(rpl_localtime): Modify _environ and _wenviron without using _putenv.
* lib/tzset.c: Include <wchar.h>.
(rpl_tzset): Modify _environ and _wenviron without using _putenv.
* lib/wcsftime.c (rpl_wcsftime): Likewise.
diff --git a/lib/ctime.c b/lib/ctime.c
index a11adc5c74..8c54ef463c 100644
--- a/lib/ctime.c
+++ b/lib/ctime.c
@@ -21,6 +21,9 @@
#include <stdlib.h>
#include <string.h>
+#if defined _WIN32 && ! defined __CYGWIN__
+# include <wchar.h>
+#endif
#undef ctime
@@ -52,7 +55,22 @@ rpl_ctime (const time_t *tp)
responsibility. */
const char *tz = getenv ("TZ");
if (tz != NULL && strchr (tz, '/') != NULL)
- _putenv ("TZ=");
+ {
+ /* Neutralize it, in a way that is multithread-safe.
+ (If we were to use _putenv ("TZ="), it would free the memory allocated
+ for the environment variable "TZ", and thus other threads that are
+ using the previously fetched value of getenv ("TZ") could crash.) */
+ char **env = _environ;
+ wchar_t **wenv = _wenviron;
+ if (env != NULL)
+ for (char *s = env; *s != NULL; s++)
+ if (s[0] == 'T' && s[1] == 'Z' && s[2] == '=')
+ s[0] = '$';
+ if (wenv != NULL)
+ for (wchar_t *ws = wenv; *ws != NULL; ws++)
+ if (ws[0] == L'T' && ws[1] == L'Z' && ws[2] == L'=')
+ ws[0] = L'$';
+ }
#endif
return ctime (tp);
diff --git a/lib/localtime.c b/lib/localtime.c
index bdea1cab10..f0e91ac647 100644
--- a/lib/localtime.c
+++ b/lib/localtime.c
@@ -21,6 +21,9 @@
#include <stdlib.h>
#include <string.h>
+#if defined _WIN32 && ! defined __CYGWIN__
+# include <wchar.h>
+#endif
#undef localtime
@@ -52,7 +55,22 @@ rpl_localtime (const time_t *tp)
responsibility. */
const char *tz = getenv ("TZ");
if (tz != NULL && strchr (tz, '/') != NULL)
- _putenv ("TZ=");
+ {
+ /* Neutralize it, in a way that is multithread-safe.
+ (If we were to use _putenv ("TZ="), it would free the memory allocated
+ for the environment variable "TZ", and thus other threads that are
+ using the previously fetched value of getenv ("TZ") could crash.) */
+ char **env = _environ;
+ wchar_t **wenv = _wenviron;
+ if (env != NULL)
+ for (char *s = env; *s != NULL; s++)
+ if (s[0] == 'T' && s[1] == 'Z' && s[2] == '=')
+ s[0] = '$';
+ if (wenv != NULL)
+ for (wchar_t *ws = wenv; *ws != NULL; ws++)
+ if (ws[0] == L'T' && ws[1] == L'Z' && ws[2] == L'=')
+ ws[0] = L'$';
+ }
#endif
return localtime (tp);
diff --git a/lib/tzset.c b/lib/tzset.c
index 0eb8c161f4..f307f0c3d1 100644
--- a/lib/tzset.c
+++ b/lib/tzset.c
@@ -24,6 +24,9 @@
#include <stdlib.h>
#include <string.h>
+#if defined _WIN32 && ! defined __CYGWIN__
+# include <wchar.h>
+#endif
void
rpl_tzset (void)
@@ -54,7 +57,22 @@ rpl_tzset (void)
responsibility. */
const char *tz = getenv ("TZ");
if (tz != NULL && strchr (tz, '/') != NULL)
- _putenv ("TZ=");
+ {
+ /* Neutralize it, in a way that is multithread-safe.
+ (If we were to use _putenv ("TZ="), it would free the memory allocated
+ for the environment variable "TZ", and thus other threads that are
+ using the previously fetched value of getenv ("TZ") could crash.) */
+ char **env = _environ;
+ wchar_t **wenv = _wenviron;
+ if (env != NULL)
+ for (char *s = env; *s != NULL; s++)
+ if (s[0] == 'T' && s[1] == 'Z' && s[2] == '=')
+ s[0] = '$';
+ if (wenv != NULL)
+ for (wchar_t *ws = wenv; *ws != NULL; ws++)
+ if (ws[0] == L'T' && ws[1] == L'Z' && ws[2] == L'=')
+ ws[0] = L'$';
+ }
/* On native Windows, tzset() is deprecated. Use _tzset() instead. See
<https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/posix-tzset>
diff --git a/lib/wcsftime.c b/lib/wcsftime.c
index 93e0470dd3..d8b471ab57 100644
--- a/lib/wcsftime.c
+++ b/lib/wcsftime.c
@@ -53,7 +53,22 @@ rpl_wcsftime (wchar_t *buf, size_t bufsize, const wchar_t *format, const struct
responsibility. */
const char *tz = getenv ("TZ");
if (tz != NULL && strchr (tz, '/') != NULL)
- _putenv ("TZ=");
+ {
+ /* Neutralize it, in a way that is multithread-safe.
+ (If we were to use _putenv ("TZ="), it would free the memory allocated
+ for the environment variable "TZ", and thus other threads that are
+ using the previously fetched value of getenv ("TZ") could crash.) */
+ char **env = _environ;
+ wchar_t **wenv = _wenviron;
+ if (env != NULL)
+ for (char *s = env; *s != NULL; s++)
+ if (s[0] == 'T' && s[1] == 'Z' && s[2] == '=')
+ s[0] = '$';
+ if (wenv != NULL)
+ for (wchar_t *ws = wenv; *ws != NULL; ws++)
+ if (ws[0] == L'T' && ws[1] == L'Z' && ws[2] == L'=')
+ ws[0] = L'$';
+ }
#endif
return wcsftime (buf, bufsize, format, tp);
next prev parent reply other threads:[~2024-02-09 20:22 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-09 17:43 MT-unsafe time modules Bruno Haible
2024-02-09 20:22 ` Bruno Haible [this message]
2024-02-10 11:10 ` Bruno Haible
2024-02-11 12:46 ` localtime on native Windows Bruno Haible
2024-02-13 2:02 ` Paul Eggert
2024-02-18 2:38 ` Bruno Haible
2024-02-18 4:50 ` Paul Eggert
2024-02-18 14:38 ` Bruno Haible
2024-02-18 19:05 ` Paul Eggert
2024-02-11 10:43 ` MT-unsafe time modules Bruno Haible
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2118215.VsPgYW4pTa@nimes \
--to=bruno@clisp.org \
--cc=bug-gnulib@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).