diff --git a/std/process.d b/std/process.d index 04f20c886..2d10a83d9 100644 --- a/std/process.d +++ b/std/process.d @@ -98,6 +98,9 @@ version (Windows) import std.windows.syserror; } +import core.exception : OutOfMemoryError; + +import std.exception : enforce; import std.internal.cstring; import std.range.primitives; import std.stdio; @@ -342,6 +345,7 @@ version (Posix) private enum InternalError : ubyte chdir, getrlimit, doubleFork, + malloc, } /* @@ -510,9 +514,9 @@ private Pid spawnProcessImpl(scope const(char[])[] args, if (!(config & Config.inheritFDs)) { // NOTE: malloc() and getrlimit() are not on the POSIX async - // signal safe functions list, but practically this should not - // be a problem. Tha Java VM and CPython also use malloc() in - // its own implementation. + // signal safe functions list, but practically this should + // not be a problem. Java VM and CPython also use malloc() + // in its own implementation via opendir(). import core.stdc.stdlib : malloc; import core.sys.posix.poll : pollfd, poll, POLLNVAL; import core.sys.posix.sys.resource : rlimit, getrlimit, RLIMIT_NOFILE; @@ -530,6 +534,10 @@ private Pid spawnProcessImpl(scope const(char[])[] args, // Call poll() to see which ones are actually open: auto pfds = cast(pollfd*) malloc(pollfd.sizeof * maxToClose); + if (pfds is null) + { + abortOnError(forkPipeOut, InternalError.malloc, .errno); + } foreach (i; 0 .. maxToClose) { pfds[i].fd = i + 3; @@ -646,6 +654,9 @@ private Pid spawnProcessImpl(scope const(char[])[] args, assert(config & Config.detached); errorMsg = "Failed to fork twice"; break; + case InternalError.malloc: + errorMsg = "Failed to allocate memory"; + break; case InternalError.noerror: assert(false); } @@ -1516,7 +1527,6 @@ private: version (Posix) int performWait(bool block) @trusted { - import std.exception : enforce; enforce!ProcessException(owned, "Can't wait on a detached process"); if (_processID == terminated) return _exitCode; int exitCode; @@ -1566,7 +1576,6 @@ private: { int performWait(bool block) @trusted { - import std.exception : enforce; enforce!ProcessException(owned, "Can't wait on a detached process"); if (_processID == terminated) return _exitCode; assert(_handle != INVALID_HANDLE_VALUE); @@ -1812,7 +1821,6 @@ void kill(Pid pid) /// ditto void kill(Pid pid, int codeOrSignal) { - import std.exception : enforce; enforce!ProcessException(pid.owned, "Can't kill detached process"); version (Windows) { @@ -3342,7 +3350,6 @@ static: */ string opIndex(scope const(char)[] name) @safe { - import std.exception : enforce; string value; enforce(getImpl(name, value), "Environment variable not found: "~name); return value; @@ -3411,7 +3418,7 @@ static: { version (Posix) { - import std.exception : enforce, errnoEnforce; + import std.exception : errnoEnforce; if (value is null) { remove(name); @@ -3431,7 +3438,6 @@ static: } else version (Windows) { - import std.exception : enforce; enforce( SetEnvironmentVariableW(name.tempCStringW(), value.tempCStringW()), sysErrorString(GetLastError()) @@ -3541,7 +3547,6 @@ static: } else version (Windows) { - import std.exception : enforce; import std.uni : toUpper; auto envBlock = GetEnvironmentStringsW(); enforce(envBlock, "Failed to retrieve environment variables."); @@ -3914,6 +3919,7 @@ extern(C) private int execv_(in string pathname, in string[] argv) { auto argv_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + argv.length)); + enforce!OutOfMemoryError(argv_ !is null, "Out of memory in std.process."); scope(exit) core.stdc.stdlib.free(argv_); toAStringz(argv, argv_); @@ -3924,8 +3930,10 @@ private int execv_(in string pathname, in string[] argv) private int execve_(in string pathname, in string[] argv, in string[] envp) { auto argv_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + argv.length)); + enforce!OutOfMemoryError(argv_ !is null, "Out of memory in std.process."); scope(exit) core.stdc.stdlib.free(argv_); auto envp_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + envp.length)); + enforce!OutOfMemoryError(envp_ !is null, "Out of memory in std.process."); scope(exit) core.stdc.stdlib.free(envp_); toAStringz(argv, argv_); @@ -3937,6 +3945,7 @@ private int execve_(in string pathname, in string[] argv, in string[] envp) private int execvp_(in string pathname, in string[] argv) { auto argv_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + argv.length)); + enforce!OutOfMemoryError(argv_ !is null, "Out of memory in std.process."); scope(exit) core.stdc.stdlib.free(argv_); toAStringz(argv, argv_); @@ -3984,8 +3993,10 @@ version (Posix) else version (Windows) { auto argv_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + argv.length)); + enforce!OutOfMemoryError(argv_ !is null, "Out of memory in std.process."); scope(exit) core.stdc.stdlib.free(argv_); auto envp_ = cast(const(char)**)core.stdc.stdlib.malloc((char*).sizeof * (1 + envp.length)); + enforce!OutOfMemoryError(envp_ !is null, "Out of memory in std.process."); scope(exit) core.stdc.stdlib.free(envp_); toAStringz(argv, argv_);