From 5ce534459330c466ec1da3619ac2665d52b7d99a Mon Sep 17 00:00:00 2001 From: chloekek Date: Fri, 26 Apr 2024 00:56:55 +0200 Subject: [PATCH] Promote `std.process.Config.preExecFunction` to a delegate 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; } --- ...process.Config.preExecFunction-delegate.dd | 38 +++++++++++++++++++ std/process.d | 20 +++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 changelog/std.process.Config.preExecFunction-delegate.dd diff --git a/changelog/std.process.Config.preExecFunction-delegate.dd b/changelog/std.process.Config.preExecFunction-delegate.dd new file mode 100644 index 00000000000..e9b13b3c268 --- /dev/null +++ b/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; +} +------- diff --git a/std/process.d b/std/process.d index 494910f3535..fbdb2e48ea9 100644 --- a/std/process.d +++ b/std/process.d @@ -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. @@ -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; } }