Skip to content

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

Closed

Description

@tysonclugg

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).

Activity

  1. added this to the 0.7.0 milestone on Jul 12, 2020
  2. tgschultz commented on Jul 14, 2020

    @tgschultz
    Contributor

    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.

  3. daurnimator commented on Aug 16, 2020

    @daurnimator
    Contributor

    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?).

  4. added
    proposalThis issue suggests language modifications. If it also has the "accepted" label then it is planned.
    on Oct 17, 2020
  5. changed the title [-]`std.ChildProcess.exec` calls `spawn` (fork/exec) instead of `exec`[/-] [+]rename `std.ChildProcess.exec` to avoid ambiguity with posix exec which replaces current image with new process[/+] on Oct 17, 2020
  6. modified the milestones: 0.7.0, 0.8.0 on Oct 17, 2020
  7. modified the milestones: 0.8.0, 0.9.0 on May 19, 2021
  8. modified the milestones: 0.9.0, 0.11.0 on Nov 23, 2021
  9. nektro commented on Dec 30, 2021

    @nektro
    Contributor

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

  10. tysonclugg commented on Aug 1, 2022

    @tysonclugg
    Author

    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.

  11. tysonclugg commented on Aug 1, 2022

    @tysonclugg
    Author

    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.

  12. tysonclugg commented on Aug 1, 2022

    @tysonclugg
    Author

    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.

  13. matu3ba commented on Jan 3, 2023

    @matu3ba
    Contributor

    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.

  14. modified the milestones: 0.15.0, 0.12.0 on Oct 22, 2023
  15. added
    breakingImplementing this issue could cause existing code to no longer compile or have different behavior.
    on Oct 22, 2023
  16. added a commit that references this issue on Oct 22, 2023
    fd2239b
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    acceptedThis proposal is planned.breakingImplementing this issue could cause existing code to no longer compile or have different behavior.proposalThis issue suggests language modifications. If it also has the "accepted" label then it is planned.standard libraryThis issue involves writing Zig code for the standard library.

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions