Is there a windows eauivalent of `std::os::unix::process::CommandExt::exec()`?

Hi All,

I'm writing a windows only tool that creates shims for various CLI commands. I'm a relatively new windows user and I'm not sure how things works on windows. In Unix there's std::os::unix::process::CommandExt::exec() which does not fork a child but replaces current process with a new one. Is there an equivalent method in windows?

If I'm using regular Command.spawn() it behaves badly on tools that do something and exit (the prompt returns and only later the output is printed to the terminal) but it's really unusable on commands that need to stay in focus (e.g. nvim).

Of course I can always use Command.status which seems to behave well but it seems to be wasteful to always wrap a command with another.

Is there a way to exec a process in windows like in unix? Maybe using some windows specific API?

Thanks

Haim

No, Windows doesn't have an equivalent to exec() on Unix. Windows has a single syscall to create a new process unlike Unix which uses fork()+exec(). (Newer Unix systems often have posix_spawn for creating a new process in one go like Windows, but fork()+exec() is still common.) The closest you can have on Windows is to spawn a new process and then wait for it to exit before exitting yourself.

For reference, this is the approach that cargo run uses, the linked documentation also explains what happens on Windows:

ProcessBuilder in cargo_util - Rust

Looking at the source code, it does use Command.status() on Windows; but furthermore it also makes sure that a received Ctrl+C – when the child process can handle it without terminating – doesn't terminate the parent either (which would take down both processes).

I'm not sure it there's any self-contained crate that offers a similar kind of abstraction.

3 Likes

That's how Microsoft OSes behaved since PC DOS 1.0. The ability to replace a current process with other was handled on the language runtime level (e.g. Turbo Pascall offeren .CHN files and chain function for that) but after computers with 64KiB of RAM have become rare that ability have disappeared (starting from Turbo Pascal 4.0 there are no such ability) and Windows never had such ability.

Even posix_spawn is just a libc abstraction, still using a pair of syscalls to fork (or vfork) and exec.

Thank you all for the detailed answers.

I have a follow up question then, I remember once writing a process wrapper to run in kubernetes and I had to make sure all signals (not just ctrl-c are passed to the forked process. On top of what @steffahn referenced (thank you for this link, very helpful :slight_smile:) are there other things or signals I have to take care of?

Thanks

Answering my own question, According to this stackoverflow question I only need to handle ctrl-c.

Thanks

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.