This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add GETENV_LOCK
authorKarl Williamson <khw@cpan.org>
Tue, 1 Dec 2020 14:44:18 +0000 (07:44 -0700)
committerKarl Williamson <khw@cpan.org>
Sun, 20 Dec 2020 05:00:30 +0000 (22:00 -0700)
get_env() needs to lock other threads from writing to the environment
while it is executing.  It may need to have an exclusive lock if those
threads can clobber its buffer before it gets a chance to save them.
The previous commit has added a Configure probe which tells us if that
is the case.  This commit uses it to select which type of mutex to use.

inline.h
perl.h

index c186372..dbfb89a 100644 (file)
--- a/inline.h
+++ b/inline.h
@@ -2654,7 +2654,7 @@ Perl_mortal_getenv(const char * str)
         return getenv(str);
     }
 
-    ENV_LOCK;
+    GETENV_LOCK;
 
     ret = getenv(str);
 
@@ -2662,7 +2662,8 @@ Perl_mortal_getenv(const char * str)
         ret = SvPVX(sv_2mortal(newSVpv(ret, 0)));
     }
 
-    ENV_UNLOCK;
+    GETENV_UNLOCK;
+
     return ret;
 }
 
diff --git a/perl.h b/perl.h
index 9243ca8..cbb6905 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -7009,6 +7009,21 @@ cannot have changed since the precalculation.
 #  define ENV_READ_UNLOCK     PERL_READ_UNLOCK(&PL_env_mutex)
 #  define ENV_INIT            PERL_RW_MUTEX_INIT(&PL_env_mutex)
 #  define ENV_TERM            PERL_RW_MUTEX_DESTROY(&PL_env_mutex)
+
+   /* On platforms where the static buffer contained in getenv() is per-thread
+    * rather than process-wide, another thread executing a getenv() at the same
+    * time won't destroy ours before we have copied the result safely away and
+    * unlocked the mutex.  On such platforms (which is most), we can have many
+    * readers of the environment at the same time. */
+#  ifdef GETENV_PRESERVES_OTHER_THREAD
+#    define GETENV_LOCK    ENV_READ_LOCK
+#    define GETENV_UNLOCK  ENV_READ_UNLOCK
+#  else
+     /* If, on the other hand, another thread could zap our getenv() return, we
+      * need to keep them from executing until we are done */
+#    define GETENV_LOCK    ENV_LOCK
+#    define GETENV_UNLOCK  ENV_UNLOCK
+#  endif
 #else
 #  define ENV_LOCK        NOOP
 #  define ENV_UNLOCK      NOOP
@@ -7016,6 +7031,8 @@ cannot have changed since the precalculation.
 #  define ENV_READ_UNLOCK NOOP
 #  define ENV_INIT        NOOP
 #  define ENV_TERM        NOOP
+#  define GETENV_LOCK     NOOP
+#  define GETENV_UNLOCK   NOOP
 #endif
 
 #ifndef PERL_NO_INLINE_FUNCTIONS