Skip to content

Commit b4a1e47

Browse files
committed
Gracefully shutdown watcher via stdin EOF
When stdin is a pipe (not a TTY), spawn a background thread that monitors for EOF. This allows a parent process (such as the test harness) to signal a graceful shutdown by closing stdin, without relying on signals or lock file removal.
1 parent 454186f commit b4a1e47

1 file changed

Lines changed: 16 additions & 1 deletion

File tree

rewatch/src/watcher.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ use anyhow::{Context, Result};
1313
use futures_timer::Delay;
1414
use notify::event::ModifyKind;
1515
use notify::{Config, Error, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
16+
use std::io::{IsTerminal, Read};
1617
use std::path::{Path, PathBuf};
1718
use std::sync::Arc;
1819
use std::sync::Mutex;
20+
use std::sync::atomic::{AtomicBool, Ordering};
1921
use std::time::{Duration, Instant};
2022

2123
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
@@ -180,10 +182,23 @@ async fn async_watch(
180182
})
181183
.expect("Error setting Ctrl-C handler");
182184

185+
// When stdin is a pipe (not a TTY), monitor it for EOF so that the
186+
// parent process can signal a graceful shutdown by closing stdin.
187+
let stdin_closed = Arc::new(AtomicBool::new(false));
188+
let stdin_closed_clone = Arc::clone(&stdin_closed);
189+
if !std::io::stdin().is_terminal() {
190+
std::thread::spawn(move || {
191+
let mut buf = [0u8; 1];
192+
// This blocks until EOF (Ok(0)) or an error occurs.
193+
let _ = std::io::stdin().read(&mut buf);
194+
stdin_closed.store(true, Ordering::Relaxed);
195+
});
196+
}
197+
183198
let mut initial_build = true;
184199

185200
loop {
186-
if *ctrlc_pressed_clone.lock().unwrap() {
201+
if *ctrlc_pressed_clone.lock().unwrap() || stdin_closed_clone.load(Ordering::Relaxed) {
187202
if show_progress {
188203
println!("\nExiting...");
189204
}

0 commit comments

Comments
 (0)