tokio: Cannot run any command with piped stdin with Nightly toolchain

Version tokio v1.18.2

Toolchains

cargo 1.60.0 (d1fd9fe2c 2022-03-01)
cargo 1.62.0-nightly (a44758ac8 2022-05-04)

Platform Windows 11

Description I cannot spawn any tokio::process::Comand with a piped stdin in the Nightly toolchain.

I tried this code:

use tokio::process::Command;
use std::process::Stdio;

#[tokio::main]
async fn main() {
    Command::new("cmd")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn()
        .unwrap();
}

I did not expect any output because it’s being spawned.

Running on the stable toolchain:

image

Instead, when running with the nightly toolchain, it throws this error:

image

If I make it inherit stdin (default behavior):

Command::new("cmd")
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .spawn()
        .unwrap();

It will run just fine in the nightly toolchain:

image

Am I missing something maybe ? 🤔

Thanks!

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 16 (7 by maintainers)

Commits related to this issue

Most upvoted comments

It’s unfortunate that libraries depend on the child process pipes being asynchronous ones, since that wasn’t a documented promise in std. It seems we have two ways forward:

  1. Document that the .as_raw_handle() from a std::process::ChildStd{in,out,err} is always an asynchronous pipe on Windows. This means std has to spawn a thread to copy over data from the async pipe into a new sync pipe when the pipe is given to another Command. Or:
  2. Document that we don’t provide that guarantee, and wait for existing libraries to adapt before changing the actual implementation a few releases later.

For 2, we could add something like a .async_pipes(true) to std::os::windows::process::CommandExt so there’s a way to explicitly request async pipes.

If you provide an async_pipes config option, then it shouldn’t be a problem to add calls to it. We should be able to use a build script to detect the version of Rust and only call it on versions where it exists.

Unfortunately, I don’t think it’s possible to change whether Tokio wraps the standard library Command struct due to backwards compatibility.

Filed a regression issue in https://github.com/rust-lang/rust/issues/97124. We’ll revert the PR on the upcoming 1.62 beta release, and most likely on nightly as well.