diff --git a/crates/turborepo-lib/src/process/mod.rs b/crates/turborepo-lib/src/process/mod.rs index da7bd0a5bebdc..e4a900d1a8f6e 100644 --- a/crates/turborepo-lib/src/process/mod.rs +++ b/crates/turborepo-lib/src/process/mod.rs @@ -60,6 +60,19 @@ impl ProcessManager { let use_pty = !cfg!(windows) && atty::is(atty::Stream::Stdout); Self::new(use_pty) } + + /// Returns whether children will be spawned attached to a pseudoterminal + pub fn use_pty(&self) -> bool { + self.use_pty + } + + /// Returns whether or not closing a child's stdin will result in it + /// immediately exiting. + pub fn closing_stdin_ends_process(&self) -> bool { + // Processes spawned hooked up to ConPTY on Windows will immediately exit + // if their stdin is closed. We avoid closing stdin in this case. + cfg!(windows) && self.use_pty + } } impl ProcessManager { diff --git a/crates/turborepo-lib/src/task_graph/visitor.rs b/crates/turborepo-lib/src/task_graph/visitor.rs index 105ca671f0ad3..27f301ca42c3b 100644 --- a/crates/turborepo-lib/src/task_graph/visitor.rs +++ b/crates/turborepo-lib/src/task_graph/visitor.rs @@ -956,7 +956,7 @@ impl ExecContext { // Even if user does not have the TUI and cannot interact with a task, we keep // stdin open for persistent tasks as some programs will shut down if stdin is // closed. - if !self.takes_input { + if !self.takes_input && !self.manager.closing_stdin_ends_process() { process.stdin(); }