Skip to content

Commit ba0de15

Browse files
committed
[std.process] Make environment use ReadWriteMutex
Fixes #10580. Make getEnvironPtr `@system`. Use a ReadWriteMutex to protect reading and writing to environment. Add `scope` to `getImpl` callback parameter. Warning 1: This (currently) removes `nothrow @nogc` from `remove`. Warning 2: I am not that experienced with locks, so bear that in mind, I may have done something wrong. Or there may be a better solution, please let me know.
1 parent 955c6e3 commit ba0de15

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

std/process.d

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ $(LREF environment), $(LREF thisProcessID) and $(LREF thisThreadID).
9090
module std.process;
9191

9292
import core.thread : ThreadID;
93+
import core.sync.rwmutex;
9394

9495
version (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
/**
180188
Manipulates _environment variables using an associative-array-like
181189
interface.
@@ -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

Comments
 (0)