Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[std.process] Make environment use a ReadWriteMutex #10611

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions std/process.d
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ $(LREF environment), $(LREF thisProcessID) and $(LREF thisThreadID).
module std.process;

import core.thread : ThreadID;
import core.sync.rwmutex;

version (Posix)
{
Expand Down Expand Up @@ -160,6 +161,13 @@ private
// Environment variable manipulation.
// =============================================================================

shared ReadWriteMutex mutex;

shared static this()
{
mutex = new shared ReadWriteMutex(mutex.Policy.PREFER_READERS);
}

/**
Manipulates _environment variables using an associative-array-like
interface.
Expand Down Expand Up @@ -259,12 +267,14 @@ static:
import std.exception : enforce, errnoEnforce;
if (value is null)
{
// Note: remove needs write lock
remove(name);
return value;
}
if (core.sys.posix.stdlib.setenv(name.tempCString(), value.tempCString(), 1) != -1)
synchronized (mutex.writer)
{
return value;
if (core.sys.posix.stdlib.setenv(name.tempCString(), value.tempCString(), 1) != -1)
return value;
}
// The default errno error message is very uninformative
// in the most common case, so we handle it manually.
Expand All @@ -277,6 +287,8 @@ static:
else version (Windows)
{
import std.windows.syserror : wenforce;

synchronized (mutex.writer)
wenforce(
SetEnvironmentVariableW(name.tempCStringW(), value.tempCStringW()),
);
Expand All @@ -296,8 +308,9 @@ static:
multi-threaded programs. See e.g.
$(LINK2 https://www.gnu.org/software/libc/manual/html_node/Environment-Access.html#Environment-Access, glibc).
*/
void remove(scope const(char)[] name) @trusted nothrow @nogc
void remove(scope const(char)[] name) @trusted //nothrow @nogc
thewilsonator marked this conversation as resolved.
Show resolved Hide resolved
{
synchronized (mutex.writer)
version (Windows) SetEnvironmentVariableW(name.tempCStringW(), null);
else version (Posix) core.sys.posix.stdlib.unsetenv(name.tempCString());
else static assert(0);
Expand Down Expand Up @@ -329,6 +342,8 @@ static:
{
if (name is null)
return false;

synchronized (mutex.reader)
version (Posix)
return core.sys.posix.stdlib.getenv(name.tempCString()) !is null;
else version (Windows)
Expand Down Expand Up @@ -363,6 +378,8 @@ static:
{
import std.conv : to;
string[string] aa;

synchronized (mutex.reader)
version (Posix)
{
auto environ = getEnvironPtr;
Expand Down Expand Up @@ -428,12 +445,13 @@ private:
// Retrieves the environment variable. Calls `sink` with a
// temporary buffer of OS characters, or `null` if the variable
// doesn't exist.
void getImpl(scope const(char)[] name, scope void delegate(const(OSChar)[]) @safe sink) @trusted
void getImpl(scope const(char)[] name, scope void delegate(scope const(OSChar)[]) @safe sink) @trusted
{
// fix issue https://issues.dlang.org/show_bug.cgi?id=24549
if (name is null)
return sink(null);

synchronized (mutex.reader)
version (Windows)
{
// first we ask windows how long the environment variable is,
Expand Down
Loading