@@ -90,6 +90,7 @@ $(LREF environment), $(LREF thisProcessID) and $(LREF thisThreadID).
9090module std.process ;
9191
9292import core.thread : ThreadID;
93+ import core.sync.rwmutex ;
9394
9495version (Posix )
9596{
@@ -149,7 +150,7 @@ private
149150 version (Darwin)
150151 {
151152 extern (C ) char *** _NSGetEnviron() nothrow ;
152- const (char ** ) getEnvironPtr () @trusted
153+ const (char ** ) getEnvironPtr () @system
153154 {
154155 return * _NSGetEnviron;
155156 }
@@ -158,7 +159,7 @@ private
158159 {
159160 // Made available by the C runtime:
160161 extern (C ) extern __gshared const char ** environ;
161- const (char ** ) getEnvironPtr () @trusted
162+ const (char ** ) getEnvironPtr () @system
162163 {
163164 return environ;
164165 }
@@ -176,6 +177,13 @@ private
176177// Environment variable manipulation.
177178// =============================================================================
178179
180+ shared ReadWriteMutex mutex;
181+
182+ shared static this ()
183+ {
184+ mutex = new shared ReadWriteMutex (mutex.Policy.PREFER_READERS );
185+ }
186+
179187/**
180188Manipulates _environment variables using an associative-array-like
181189interface.
@@ -275,12 +283,14 @@ static:
275283 import std.exception : enforce, errnoEnforce;
276284 if (value is null )
277285 {
286+ // Note: remove needs write lock
278287 remove(name);
279288 return value;
280289 }
281- if ( core.sys.posix.stdlib.setenv (name.tempCString(), value.tempCString(), 1 ) != - 1 )
290+ synchronized (mutex.writer )
282291 {
283- return value;
292+ if (core.sys.posix.stdlib.setenv (name.tempCString(), value.tempCString(), 1 ) != - 1 )
293+ return value;
284294 }
285295 // The default errno error message is very uninformative
286296 // in the most common case, so we handle it manually.
@@ -293,6 +303,8 @@ static:
293303 else version (Windows )
294304 {
295305 import std.windows.syserror : wenforce;
306+
307+ synchronized (mutex.writer)
296308 wenforce(
297309 SetEnvironmentVariableW(name.tempCStringW(), value.tempCStringW()),
298310 );
@@ -312,8 +324,9 @@ static:
312324 multi-threaded programs. See e.g.
313325 $(LINK2 https://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access, glibc).
314326 */
315- void remove (scope const (char )[] name) @trusted nothrow @nogc
327+ void remove (scope const (char )[] name) @trusted // nothrow @nogc
316328 {
329+ synchronized (mutex.writer)
317330 version (Windows ) SetEnvironmentVariableW(name.tempCStringW(), null );
318331 else version (Posix ) core.sys.posix.stdlib.unsetenv (name.tempCString());
319332 else static assert (0 );
@@ -345,6 +358,8 @@ static:
345358 {
346359 if (name is null )
347360 return false ;
361+
362+ synchronized (mutex.reader)
348363 version (Posix )
349364 return core.sys.posix.stdlib.getenv (name.tempCString()) ! is null ;
350365 else version (Windows )
@@ -379,6 +394,8 @@ static:
379394 {
380395 import std.conv : to;
381396 string [string ] aa;
397+
398+ synchronized (mutex.reader)
382399 version (Posix )
383400 {
384401 auto environ = getEnvironPtr;
@@ -444,12 +461,13 @@ private:
444461 // Retrieves the environment variable. Calls `sink` with a
445462 // temporary buffer of OS characters, or `null` if the variable
446463 // doesn't exist.
447- void getImpl (scope const (char )[] name, scope void delegate (const (OSChar)[]) @safe sink) @trusted
464+ void getImpl (scope const (char )[] name, scope void delegate (scope const (OSChar)[]) @safe sink) @trusted
448465 {
449466 // fix issue https://issues.dlang.org/show_bug.cgi?id=24549
450467 if (name is null )
451468 return sink (null );
452469
470+ synchronized (mutex.reader)
453471 version (Windows )
454472 {
455473 // first we ask windows how long the environment variable is,
0 commit comments