The current implementation of spawnProcessPosix is broken on systems
with a large `ulimit -n` because it always OOMs making it impossible
to spawn processes. Using the libc implementation, when available, for
doing file descriptor operations en-mass partially solves this problem.
Signed-off-by: Andrei Horodniceanu <a.horodniceanu@proton.me>
std.process.Config.preExecDelegate is just like
std.process.Config.preExecFunction, but can capture an environment, for
example:
import core.sys.linux.sys.prctl : PR_SET_PDEATHSIG, prctl;
import std.process : Config, execute;
void runProgram(int pdeathsig)
{
execute(
["program"],
config: Config(
preExecDelegate: () @trusted =>
prctl(PR_SET_PDEATHSIG, pdeathsig, 0, 0, 0) != -1,
),
);
}
preExecFunction is retained for backwards compatibility. If both
preExecFunction and preExecDelegate are given, both are called.
std.process.Config.preExecFunction is now a delegate instead of a function
pointer, and can therefore capture an environment, for example:
import core.sys.linux.sys.prctl : PR_SET_PDEATHSIG, prctl;
import std.process : Config, execute;
void runProgram(int pdeathsig)
{
execute(
["program"],
config: Config(
preExecFunction: () @trusted =>
prctl(PR_SET_PDEATHSIG, pdeathsig, 0, 0, 0) != -1,
),
);
}
Despite function pointers implicitly converting to delegates, this is a
backwards-incompatible change, as user code may rely on the field being a
function pointer. For example, code like the following will no longer compile:
import std.process : Config;
nothrow pure @nogc @safe
bool f() { return true; }
void example()
{
auto config = Config(preExecFunction: &f);
bool function() g = config.preExecFunction;
}
In the forked process, the array "pfds" is allocated and is never free'd.
That's a problem if you're going to spawn and keep running a lot of processes, since it's a quite big array.
`sysErrorString` throws an exception for unknown error codes (e.g. from
libraries using `SetLastError`) and hence could hide the actual error
that caused the call to `sysErrorString`.
The new helper function wraps the error code lookup and returns `Error X`
on failure.
This ensures that the actual error message won't be suppressed when the
lookup error code => message fails. The exception will also be more
informative because `WindowsException` is explicitly intended for
Windows API errors.
combines the very common constraint
`isInputRange!R && !isInfinite!R && isSomeChar!(ElementEncodingType!R)`
and adds a bunch of documentation with examples for users to understand
it better. This should lower the neccessary needed technical insight to
read basic docs, especially std.path and std.file docs.
Previously, if this call to 'open' failed, it would result in a spurious
test failure. Now, it instead causes the test to be skipped.
Possibly related to https://issues.dlang.org/show_bug.cgi?id=22350
`wait(Pid, Duration)` allows to wait until the process terminates
or the timeout expires.
It's currently windows-only because a decent posix implementation
is quite difficult and this allows us to sort out the API beforehand.
The temporary buffer returned by `tempCString` was assigned to a `char*`
and hence destroyed after the statement. This worked by accident for
small URL's because the space was allocated on the stack and not
overwritten before forking.