Skip to content

Commit

Permalink
Promote std.process.Config.preExecFunction to a delegate
Browse files Browse the repository at this point in the history
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;
    }
  • Loading branch information
chloekek committed Apr 25, 2024
1 parent 4b2ea30 commit 5ce5344
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 2 deletions.
38 changes: 38 additions & 0 deletions changelog/std.process.Config.preExecFunction-delegate.dd
@@ -0,0 +1,38 @@
Promote `std.process.Config.preExecFunction` to a delegate

$(LINK2 $(ROOT_DIR)phobos/std_process.html#.Config.preExecFunction,
`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;
}
-------
20 changes: 18 additions & 2 deletions std/process.d
Expand Up @@ -1271,6 +1271,22 @@ version (Posix)
assert(received);
}

version (Posix)
@safe unittest
{
foreach (i; 0 .. 3)
{
auto config = Config(
preExecFunction: delegate() @trusted {
_Exit(i);
return true;
},
);
auto pid = spawnProcess(["false"], config: config);
assert(wait(pid) == i);
}
}

/*
Implementation of spawnProcess() for Windows.
Expand Down Expand Up @@ -2188,11 +2204,11 @@ struct Config
On Windows, this member is not available.
*/
bool function() nothrow @nogc @safe preExecFunction;
bool delegate() nothrow @nogc @safe preExecFunction;
}
else version (Posix)
{
bool function() nothrow @nogc @safe preExecFunction;
bool delegate() nothrow @nogc @safe preExecFunction;
}
}

Expand Down

0 comments on commit 5ce5344

Please sign in to comment.