Fix stdin inherited by child processes when no input provided#1512
Fix stdin inherited by child processes when no input provided#1512JohnMcPMS wants to merge 3 commits intoPowerShell:mainfrom
Conversation
When invoke_command is called with input = None, the child process previously inherited the parent's stdin handle. In CI environments where the parent has a redirected pipe for stdin, this caused PowerShell child processes to block indefinitely on `$Input` (reading from the inherited pipe that never closes). The fix sets stdin to Stdio::null() when no input is provided, ensuring the child process sees an immediate EOF rather than inheriting whatever stdin handle the parent holds. Root cause: commit 1af2c8b changed the PowerShell adapter from "config": "full" to "config": "single", which routes export through a code path that calls invoke_command with no input. Previously, the full-config path always provided input so stdin was always piped. Also adds: - Integration test that detects this regression in all environments (terminal and CI) without leaving hanging threads - A -RustTestFilter parameter to build.ps1 / Test-RustProject to allow running a specific Rust test by name via the build script Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Fixes a hang where invoke_command(input=None) caused child processes to inherit the parent’s stdin (often a never-closing pipe in CI), and adds tooling + coverage to prevent regressions.
Changes:
- Set child process stdin to
Stdio::null()wheninvoke_commandis called withinput = None(ensures immediate EOF). - Add an integration test that detects stdin-inheritance regressions without leaving hanging threads.
- Add
-RustTestFiltersupport tobuild.ps1/Test-RustProjectto run a specific Rust test by name.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| lib/dsc-lib/src/dscresources/command_resource.rs | Forces stdin to null when no input is provided to avoid inherited-stdin hangs. |
| lib/dsc-lib/tests/integration/main.rs | Registers the new integration test module. |
| lib/dsc-lib/tests/integration/command_resource.rs | Adds regression test ensuring stdin is EOF when input=None. |
| helpers.build.psm1 | Adds TestFilter parameter and forwards it to cargo test. |
| build.ps1 | Adds -RustTestFilter and wires it into Test-RustProject. |
SteveL-MSFT
left a comment
There was a problem hiding this comment.
Making them pester tests means you can also revert the build changes
|
I wouldn't think your change affects the WindowsUpdate resource tests, so it might be that the image used for CI isn't sufficient for the WindowsUpdate resource tests. I'll investigate this separately and will update this PR if a fix is needed there. |
|
It actually makes me think that this fix is flawed. Those tests are relying on the behavior pre-fix; passing an input into If that behavior is supported, this change breaks it. In fact, winget explicitly uses the input stream and not the parameter. I can change our use to always provide input, but trying that I'm getting different behavior between this fix and the input swap. Was there some other fix that isn't in 3.2 that would produce better errors on an attempt to export without an Export method on the PS class? |
Perhaps what needs to happen is that if the resource indicates it receives input via stdin, we need the current behavior, but otherwise it means via parameter and stdin can be null. The resource manifest has |
SteveL-MSFT
left a comment
There was a problem hiding this comment.
Need to update so it looks at the resource manifest and if the resource doesn't read input from stdin then set it to null.
|
@JohnMcPMS I figured out the problem after doing some debugging. I had forgotten a change we made awhile back on how |
When invoke_command is called with input = None, the child process previously inherited the parent's stdin handle. In CI environments where the parent has a redirected pipe for stdin, this caused PowerShell child processes to block indefinitely on
$Input(reading from the inherited pipe that never closes).The following was able to repro the problem minimally (choose any PS adapted resource):
The fix sets stdin to Stdio::null() when no input is provided, ensuring the child process sees an immediate EOF rather than inheriting whatever stdin handle the parent holds.
Root cause: commit 1af2c8b changed the PowerShell adapter from "config": "full" to "config": "single", which routes export through a code path that calls invoke_command with no input. Previously, the full-config path always provided input so stdin was always piped.
Also adds: