mirror of
https://github.com/dlang/phobos.git
synced 2025-04-27 21:51:40 +03:00
Merge pull request #8989 from chloekek/std.process.Config.preExecFunction-delegate
Promote `std.process.Config.preExecFunction` to a delegate
This commit is contained in:
commit
8e6f77231a
2 changed files with 74 additions and 1 deletions
25
changelog/std.process.Config.preExecDelegate.dd
Normal file
25
changelog/std.process.Config.preExecDelegate.dd
Normal file
|
@ -0,0 +1,25 @@
|
|||
Add `std.process.Config.preExecDelegate`
|
||||
|
||||
$(LINK2 $(ROOT_DIR)phobos/std_process.html#.Config.preExecDelegate, `std.process.Config.preExecDelegate`)
|
||||
is just like
|
||||
$(LINK2 $(ROOT_DIR)phobos/std_process.html#.Config.preExecFunction, `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.
|
|
@ -1102,6 +1102,14 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
|
|||
}
|
||||
}
|
||||
|
||||
if (config.preExecDelegate !is null)
|
||||
{
|
||||
if (config.preExecDelegate() != true)
|
||||
{
|
||||
abortOnError(forkPipeOut, InternalError.preExec, .errno);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute program.
|
||||
core.sys.posix.unistd.execve(argz[0], argz.ptr, envz);
|
||||
|
||||
|
@ -1187,7 +1195,7 @@ private Pid spawnProcessPosix(scope const(char[])[] args,
|
|||
errorMsg = "Failed to allocate memory";
|
||||
break;
|
||||
case InternalError.preExec:
|
||||
errorMsg = "Failed to execute preExecFunction";
|
||||
errorMsg = "Failed to execute preExecFunction or preExecDelegate";
|
||||
break;
|
||||
case InternalError.noerror:
|
||||
assert(false);
|
||||
|
@ -1271,6 +1279,29 @@ version (Posix)
|
|||
assert(received);
|
||||
}
|
||||
|
||||
version (Posix)
|
||||
@system unittest
|
||||
{
|
||||
__gshared int j;
|
||||
foreach (i; 0 .. 3)
|
||||
{
|
||||
auto config = Config(
|
||||
preExecFunction: function() @trusted {
|
||||
j = 1;
|
||||
return true;
|
||||
},
|
||||
preExecDelegate: delegate() @trusted {
|
||||
// j should now be 1, as preExecFunction is called before
|
||||
// preExecDelegate is.
|
||||
_Exit(i + j);
|
||||
return true;
|
||||
},
|
||||
);
|
||||
auto pid = spawnProcess(["false"], config: config);
|
||||
assert(wait(pid) == i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Implementation of spawnProcess() for Windows.
|
||||
|
||||
|
@ -2186,13 +2217,30 @@ struct Config
|
|||
Please note that the code in this function must only use
|
||||
async-signal-safe functions.)
|
||||
|
||||
If $(LREF preExecDelegate) is also set, it is called last.
|
||||
|
||||
On Windows, this member is not available.
|
||||
*/
|
||||
bool function() nothrow @nogc @safe preExecFunction;
|
||||
|
||||
/**
|
||||
A delegate that is called before `exec` in $(LREF spawnProcess).
|
||||
It returns `true` if succeeded and otherwise returns `false`.
|
||||
|
||||
$(RED Warning:
|
||||
Please note that the code in this function must only use
|
||||
async-signal-safe functions.)
|
||||
|
||||
If $(LREF preExecFunction) is also set, it is called first.
|
||||
|
||||
On Windows, this member is not available.
|
||||
*/
|
||||
bool delegate() nothrow @nogc @safe preExecDelegate;
|
||||
}
|
||||
else version (Posix)
|
||||
{
|
||||
bool function() nothrow @nogc @safe preExecFunction;
|
||||
bool delegate() nothrow @nogc @safe preExecDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue