1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-29 19:30:36 +02:00

Warn about mutation of ‘environ’ when multi-threaded.

This is an amendment to 84bf840322.

The warning was only emitted for calling `environ', even if only reading
and no mutation occurred.

However, it is correct to read the environment in a multi-threaded
process.  It is however unsafe to mutate it.

The same logic also applies to `putenv'.

* libguile/posix.c
  (maybe_warn_about_environ_mutation): New private procedure ...
  (scm_environ): ... called here when mutating the environment ...
  (scm_putenv): ... and here.
* NEWS: Update.

Signed-off-by: Ludovic Courtès <ludo@gnu.org>
This commit is contained in:
Olivier Dion 2025-02-18 20:40:41 -05:00 committed by Ludovic Courtès
parent b8031fc965
commit 7b7340b2d9
No known key found for this signature in database
GPG key ID: 090B11993D9AEBB5
2 changed files with 21 additions and 12 deletions

2
NEWS
View file

@ -86,6 +86,8 @@ every line in a file.
in turn, would trigger warnings from 'primitive-fork' and 'environ'
suggesting they are being called in a multi-threaded context, when in
fact user code did not create any thread.
** Calling 'environ' without arguments in a multi-threaded program is OK
This used to trigger a warning, unduly.
Changes in 3.0.10 (since 3.0.9)

View file

@ -1705,6 +1705,19 @@ SCM_DEFINE (scm_uname, "uname", 0, 0, 0,
#undef FUNC_NAME
#endif /* HAVE_UNAME */
static void
maybe_warn_about_environ_mutation (void)
{
/* Mutating `environ' directly in a multi-threaded program is
undefined behavior. */
if (scm_ilength (scm_all_threads ()) != 1)
scm_display
(scm_from_latin1_string
("warning: mutating the process environment while multiple threads are running;\n"
" further behavior unspecified.\n"),
scm_current_warning_port ());
}
SCM_DEFINE (scm_environ, "environ", 0, 1, 0,
(SCM env),
"If @var{env} is omitted, return the current environment (in the\n"
@ -1716,22 +1729,13 @@ SCM_DEFINE (scm_environ, "environ", 0, 1, 0,
"then the return value is unspecified.")
#define FUNC_NAME s_scm_environ
{
/* Accessing `environ' directly in a multi-threaded program is
undefined behavior since at anytime it could point to anything else
while reading it. Not only that, but all accesses are protected by
an internal mutex of libc. Thus, it is only truly safe to modify
the environment directly in a single-threaded program. */
if (scm_ilength (scm_all_threads ()) != 1)
scm_display
(scm_from_latin1_string
("warning: call to environ while multiple threads are running;\n"
" further behavior unspecified.\n"),
scm_current_warning_port ());
if (SCM_UNBNDP (env))
return scm_makfromstrs (-1, environ);
else
{
/* Mutating the environment in a multi-threaded program is hazardous. */
maybe_warn_about_environ_mutation ();
/* Arrange to not use GC-allocated storage for what goes into
'environ' as libc might reallocate it behind our back. */
#if HAVE_CLEARENV
@ -1951,6 +1955,9 @@ SCM_DEFINE (scm_putenv, "putenv", 1, 0, 0,
int rv;
char *c_str = scm_to_locale_string (str);
/* Mutating the environment in a multi-threaded program is hazardous. */
maybe_warn_about_environ_mutation ();
/* Leave C_STR in the environment. */
/* Gnulib's `putenv' module honors the semantics described above. */