Skip to content

Windows: add context when opening NUL for child stdio fails#159425

Merged
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
Joel-Wwalker:157049-nul-error-context
Jul 18, 2026
Merged

Windows: add context when opening NUL for child stdio fails#159425
rust-bors[bot] merged 2 commits into
rust-lang:mainfrom
Joel-Wwalker:157049-nul-error-context

Conversation

@Joel-Wwalker

@Joel-Wwalker Joel-Wwalker commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Opening \\.\NUL for Stdio::Null can fail in some environments, and Command::spawn/output() passes the raw OS error through. In the reported case that was NotFound, which looks exactly like the program itself being missing. Add context saying what failed to open and for which stream:

failed to open NUL device for child stdin: The system cannot find the file specified. (os error 2)

The ErrorKind is kept. raw_os_error() on this path becomes None since the payload is now a message string. I don't see a way to make opening NUL fail in CI, so no test; verified by hand in a local build by pointing the open at a bogus device name and checking the error out of Command::output().

Fixes #157049

A failed open of \\.\NUL for Stdio::Null surfaced as a bare OS error
(usually NotFound), which reads as if the spawned program is missing.
Wrap it with the operation and stream name, preserving the ErrorKind.
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jul 17, 2026
@rustbot

rustbot commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

r? @Darksonn

rustbot has assigned @Darksonn.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: @ChrisDenton, libs
  • @ChrisDenton, libs expanded to 13 candidates
  • Random selection from 6 candidates

@Darksonn

Copy link
Copy Markdown
Member

I would also like to hear an answer to #157049 (comment). I'm concerned that the issue may have been misdiagnosed.

@Joel-Wwalker

Copy link
Copy Markdown
Contributor Author

The report does isolate the failing call: it says "After investigation, the missing path was not real_networking.exe; the failing operation was opening NUL", and includes a standalone OpenOptions::new().read(true).write(true).open("NUL") snippet for checking exactly that.

Environments where the NUL open fails do exist. The device is backed by the Null kernel driver, which can be absent or disabled, and then opening it fails with this same error; IPython hit that in the wild (ipython/ipython#9023, IOError: [Errno 2] No such file or directory: 'nul'). What we don't know is what the reporter's machine looked like, so I've asked them on the issue. Happy to wait for their answer if you'd rather.

Either way the change is scoped to the NUL open itself: it only wraps the error from that one call, so it can't mislabel an unrelated failure, and nothing changes when NUL opens fine.

Comment thread library/std/src/sys/process/windows.rs Outdated
let stream = match stdio_id {
c::STD_INPUT_HANDLE => "stdin",
c::STD_OUTPUT_HANDLE => "stdout",
_ => "stderr",

@Darksonn Darksonn Jul 18, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there really no possibility of stdio_id being something other than these three values? Perhaps we should handle unknown values by printing the integer value instead of printing stderr when it might not be stderr?

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Today it can't be anything else (the only callers are the three spawn lines passing the constants), but you're right that the arm shouldn't claim stderr for values it doesn't know. Changed it to print the raw id for anything unexpected.

@Darksonn Darksonn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original issue still seems weird, but returning a better error in this case is probably a good idea regardless.

@bors r+

View changes since this review

@rust-bors

rust-bors Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

📌 Commit d9ac1a5 has been approved by Darksonn

It is now in the queue for this repository.

@rust-bors rust-bors Bot added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 18, 2026
rust-bors Bot pushed a commit that referenced this pull request Jul 18, 2026
…uwer

Rollup of 8 pull requests

Successful merges:

 - #159425 (Windows: add context when opening NUL for child stdio fails)
 - #159467 (Add explicit `Iterator::count` impl for `str::EncodeUtf16`)
 - #157860 (Move rustdoc run-make tests into new `tests/run-make/rustdoc/`)
 - #158545 (Move `std::io::read_to_string` to `alloc::io`)
 - #159328 (tests/assembly-llvm: pin frame pointer in issue-141649 aarch64 test)
 - #159459 (Detect when trait bound requires closure to return itself)
 - #159470 (Fix string indexing in diagnostic format strings)
 - #159500 (Move compiletest CLI parsing to `cli.rs`)
@rust-bors
rust-bors Bot merged commit 291a31c into rust-lang:main Jul 18, 2026
13 checks passed
@rustbot rustbot added this to the 1.99.0 milestone Jul 18, 2026
rust-timer added a commit that referenced this pull request Jul 18, 2026
Rollup merge of #159425 - Joel-Wwalker:157049-nul-error-context, r=Darksonn

Windows: add context when opening NUL for child stdio fails

Opening `\\.\NUL` for `Stdio::Null` can fail in some environments, and `Command::spawn`/`output()` passes the raw OS error through. In the reported case that was `NotFound`, which looks exactly like the program itself being missing. Add context saying what failed to open and for which stream:

```
failed to open NUL device for child stdin: The system cannot find the file specified. (os error 2)
```

The `ErrorKind` is kept. `raw_os_error()` on this path becomes `None` since the payload is now a message string. I don't see a way to make opening NUL fail in CI, so no test; verified by hand in a local build by pointing the open at a bogus device name and checking the error out of `Command::output()`.

Fixes #157049
github-actions Bot pushed a commit to rust-lang/rustc-dev-guide that referenced this pull request Jul 20, 2026
…uwer

Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#159425 (Windows: add context when opening NUL for child stdio fails)
 - rust-lang/rust#159467 (Add explicit `Iterator::count` impl for `str::EncodeUtf16`)
 - rust-lang/rust#157860 (Move rustdoc run-make tests into new `tests/run-make/rustdoc/`)
 - rust-lang/rust#158545 (Move `std::io::read_to_string` to `alloc::io`)
 - rust-lang/rust#159328 (tests/assembly-llvm: pin frame pointer in issue-141649 aarch64 test)
 - rust-lang/rust#159459 (Detect when trait bound requires closure to return itself)
 - rust-lang/rust#159470 (Fix string indexing in diagnostic format strings)
 - rust-lang/rust#159500 (Move compiletest CLI parsing to `cli.rs`)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

On Windows, std::process::Command::output() can return misleading NotFound if opening NUL fails

3 participants