From 6b8919b37be15cc8bab9b1baf45f6166c5b0326a Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Thu, 15 May 2025 14:16:59 +0200 Subject: [PATCH] fix stdin handling for the tw watcher (#4119) --- packages/cli/src/serve/mod.rs | 2 +- packages/cli/src/serve/runner.rs | 9 ++++++--- packages/cli/src/tailwind.rs | 10 ++++++++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/cli/src/serve/mod.rs b/packages/cli/src/serve/mod.rs index 3a6238344..5fa390967 100644 --- a/packages/cli/src/serve/mod.rs +++ b/packages/cli/src/serve/mod.rs @@ -203,7 +203,7 @@ pub(crate) async fn serve_all(args: ServeArgs, tracer: &mut TraceController) -> } ServeUpdate::Exit { error } => { - _ = builder.cleanup_all().await; + _ = builder.shutdown().await; _ = devserver.shutdown().await; match error { diff --git a/packages/cli/src/serve/runner.rs b/packages/cli/src/serve/runner.rs index 610ae64ae..4598517c7 100644 --- a/packages/cli/src/serve/runner.rs +++ b/packages/cli/src/serve/runner.rs @@ -74,7 +74,7 @@ pub(crate) struct AppServer { pub(crate) cross_origin_policy: bool, // Additional plugin-type tools - pub(crate) _tw_watcher: tokio::task::JoinHandle>, + pub(crate) tw_watcher: tokio::task::JoinHandle>, } pub(crate) struct CachedFile { @@ -186,7 +186,7 @@ impl AppServer { _force_sequential: force_sequential, cross_origin_policy, fullstack, - _tw_watcher: tw_watcher, + tw_watcher, }; // Only register the hot-reload stuff if we're watching the filesystem @@ -564,7 +564,7 @@ impl AppServer { } /// Shutdown all the running processes - pub(crate) async fn cleanup_all(&mut self) -> Result<()> { + pub(crate) async fn shutdown(&mut self) -> Result<()> { self.client.soft_kill().await; if let Some(server) = self.server.as_mut() { @@ -588,6 +588,9 @@ impl AppServer { } } + // force the tailwind watcher to stop - if we don't, it eats our stdin + self.tw_watcher.abort(); + Ok(()) } diff --git a/packages/cli/src/tailwind.rs b/packages/cli/src/tailwind.rs index e907ffccf..4cd111136 100644 --- a/packages/cli/src/tailwind.rs +++ b/packages/cli/src/tailwind.rs @@ -34,8 +34,12 @@ impl TailwindCli { tailwind.install_github().await?; } - let proc = tailwind.watch(&manifest_dir, input_path, output_path)?; - proc.wait_with_output().await?; + // the tw watcher blocks on stdin, and `.wait()` will drop stdin + // unfortunately the tw watcher just deadlocks in this case, so we take the stdin manually + let mut proc = tailwind.watch(&manifest_dir, input_path, output_path)?; + let stdin = proc.stdin.take(); + proc.wait().await?; + drop(stdin); Ok(()) }) @@ -107,6 +111,8 @@ impl TailwindCli { .arg("--output") .arg(output_path) .arg("--watch") + .kill_on_drop(true) + .stdin(Stdio::piped()) .stdout(Stdio::null()) .stderr(Stdio::null()) .spawn()?;