ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.

Home Page:https://ziglang.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

rename `std.ChildProcess.exec` to avoid ambiguity with posix exec which replaces current image with new process

tysonclugg opened this issue · comments

The std.ChildProcess.exec function doesn't follow the expected behaviour of replacing the executable with the new program being exec'ed. See the SO question "Differences between fork and exec" for details on how fork and exec should behave.

Currently, std.ChildProcess.exec creates a std.ChildProcess instance and then calls its spawn method - returning an ExecResult struct:

pub fn exec(args: struct {
allocator: *mem.Allocator,
argv: []const []const u8,
cwd: ?[]const u8 = null,
cwd_dir: ?fs.Dir = null,
env_map: ?*const BufMap = null,
max_output_bytes: usize = 50 * 1024,
expand_arg0: Arg0Expand = .no_expand,
}) !ExecResult {
const child = try ChildProcess.init(args.argv, args.allocator);
defer child.deinit();
child.stdin_behavior = .Ignore;
child.stdout_behavior = .Pipe;
child.stderr_behavior = .Pipe;
child.cwd = args.cwd;
child.cwd_dir = args.cwd_dir;
child.env_map = args.env_map;
child.expand_arg0 = args.expand_arg0;
try child.spawn();

I expect that std.ChildProcess.exec should not fork or spawn, and it should have a !noreturn result (perhaps ExecError!noreturn with ExecError being much the same as a SpawnError).

However, coming from a Windows environment, this is not the behavior I expect. Should std.ChildProcess.exec be expected to follow POSIX definitions?

Perhaps instead of making it noreturn, it can simply be renamed to ChildProcess.spawn or ChildProcess.create to avoid confusion.

Yeah it might be best if we avoid exec at all.

Give that the module is ChildProcess, I don't think any "replaceCurrentProcess" doesn't make sense and belongs elsewhere (process.zig?).

any thoughts on run? doing some reworking in the above PR

Why not follow POSIX conventions?

Even in Windows, some form of POSIX has been available for the last 29 years (since Windows NT 3.1).

I didn't ask for exec to be renamed.

Regarding the POSIX question, I see a number of possible outcomes:

  1. Zig closely follows the C/C++ precedent and provides a clean mapping of zig methods to various syscalls, including those defined by POSIX. Zig provides an exec method that closely follows the POSIX spec (as per the intent of the issue as it was raised).
  2. Zig specifically opts out from trying to provide wrappers for any syscalls such as execve. You would need to use libc methods such as exec to get access to the low-level syscalls.
  3. Something between 1 & 2, which means every time a question like this pops up an ad-hoc decision will need to be made. Zig continues to provide methods like std.ChildProcess.exec that don't follow established conventions, and people coming from C/C++ backgrounds (ie: the primary target audience) keep getting tripped up because of the differences.
  4. Something else, yet to be proposed/decided.

To be clear, I'm absolutely fine with 1 and 2. I'm very much against 3, and obviously can't have an opinion on 4 until a proposal is made.

If std.ChildProcess is considered a "helper" library of abstract methods (option 4) and not a clean mapping of syscalls (option 1), then renaming exec to something else to avoid the issues of option 3 makes more sense. Perhaps run might be a good name in that case, but it should be very clear from both the method names, the documentation, and the website (where any C/C++ comparisons are made) that these abstract methods are not 1-1 replacements of the C/C++ equivalents.

then renaming exec to something else to avoid the issues of option 3 makes more sense

True, run is also used by Python and its nice and short. Rust uses Command::new, which I find not nice.
I'll create a PR.