civodul pushed a commit to branch main
in repository guile.

commit 7b7340b2d9ad6c9e34a784555e6d70acbaf0e545
Author: Olivier Dion <olivier.d...@polymtl.ca>
AuthorDate: Tue Feb 18 20:40:41 2025 -0500

    Warn about mutation of ‘environ’ when multi-threaded.
    
    This is an amendment to 84bf84032208e21d20ad13f3033d4fca3a512014.
    
    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 <l...@gnu.org>
---
 NEWS             |  2 ++
 libguile/posix.c | 31 +++++++++++++++++++------------
 2 files changed, 21 insertions(+), 12 deletions(-)

diff --git a/NEWS b/NEWS
index ff4c977de..e7641c008 100644
--- a/NEWS
+++ b/NEWS
@@ -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)
diff --git a/libguile/posix.c b/libguile/posix.c
index 61b5523af..dde77b8ee 100644
--- a/libguile/posix.c
+++ b/libguile/posix.c
@@ -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.  */

Reply via email to