diff --git a/docs/next/CHANGELOG.md b/docs/next/CHANGELOG.md index 8701dd24..36eade52 100644 --- a/docs/next/CHANGELOG.md +++ b/docs/next/CHANGELOG.md @@ -19,6 +19,7 @@ ### Fixed - `herdr --remote` now prints clean remote attach failures and SSH authentication guidance instead of Rust Debug-formatted I/O errors when SSH authentication is denied. (#1034) +- `herdr server stop` now stops Windows named-pipe servers instead of failing with `named pipes do not support I/O timeouts`. (#1113) - `herdr server stop` now waits until both server sockets are unreachable before returning, avoiding an immediate first-start failure when restarting right after replacing the binary. - macOS `herdr --remote` clients now bridge Finder-dropped image files to the remote pane instead of forwarding the local file path as typed text. (#828) - Grok Build agent detection now tracks the current Grok Build UI: panes report working while responses, tools, and subagents run, and blocked on permission prompts and question dialogs, instead of falling back to idle mid-turn. (#1017) diff --git a/src/session.rs b/src/session.rs index 4dfb2658..8abda3d1 100644 --- a/src/session.rs +++ b/src/session.rs @@ -325,7 +325,7 @@ fn send_stop_request( return Ok(None); }; if let Err(err) = stream.set_send_timeout(Some(write_timeout)) { - if err.kind() != std::io::ErrorKind::InvalidInput { + if !stop_timeout_error_allows_wait(&err) { return Err(err.to_string()); } } @@ -354,7 +354,7 @@ fn send_stop_request_inner( return Ok(None); }; if let Err(err) = stream.set_recv_timeout(Some(read_timeout)) { - if err.kind() == std::io::ErrorKind::InvalidInput { + if stop_timeout_error_allows_wait(&err) { return Ok(None); } return Err(err); @@ -368,6 +368,11 @@ fn send_stop_request_inner( Ok(Some(line)) } +fn stop_timeout_error_allows_wait(err: &std::io::Error) -> bool { + err.kind() == std::io::ErrorKind::InvalidInput + || (cfg!(windows) && err.kind() == std::io::ErrorKind::Unsupported) +} + fn stop_request_error_allows_wait(err: &std::io::Error) -> bool { matches!( err.kind(), @@ -504,6 +509,20 @@ mod tests { } } + #[test] + fn stop_timeout_invalid_input_waits_for_socket_state() { + let err = std::io::Error::from(std::io::ErrorKind::InvalidInput); + + assert!(stop_timeout_error_allows_wait(&err)); + } + + #[test] + fn stop_timeout_unsupported_waits_for_socket_state_only_on_windows() { + let err = std::io::Error::from(std::io::ErrorKind::Unsupported); + + assert_eq!(stop_timeout_error_allows_wait(&err), cfg!(windows)); + } + #[test] fn socket_timeouts_are_never_zero_duration() { assert_eq!(socket_timeout_from_remaining(Duration::ZERO), None);