feat(tty-local): implement pipe mode — tokio::process spawn, PipeControl, ADR-056 kill guard
Implements the runner case (terminal: None, no PTY) in pipe.rs: - allocate_pipe spawns via tokio::process::Command with Stdio::piped(), returning a TtyHandle with separate stdout/stderr (stderr=Some). - stdin: ChildStdin boxed as Box<dyn AsyncWrite + Send + Unpin>. - stdout/stderr: ChildStdout/ChildStderr wrapped via tokio_util::io::ReaderStream into Pin<Box<dyn Stream<Item = Bytes> + Send>> (errors map to stream EOF). - exit_code: PipeExitFuture holding the Child; poll drives Child::wait() and disarms the guard on resolve; Drop calls Child::start_kill() on cancel (ADR-056 spec-compliant kill-on-Drop, not kill_on_drop(true) alone). - control: PipeControl (no-op resize, libc::kill(pid, sig) signal on Unix, SIGKILL fallback for unknown names; non-Unix logs and relies on Drop guard). Doc comment documents the no-process-group limitation of pipe mode. Adds tokio-util (io) and tokio-stream (dev) deps. 9 unit tests cover the happy path, stdin round-trip, separate stderr, SIGTERM signal, cancel cleanup (asserts child killed via kill(pid,0)), resize no-op, unknown signal SIGKILL fallback, pid recording, and empty-command error.
This commit is contained in:
1 parent
42643be338
commit
c76b6aab7a
3 files changed
+468
-1
No files matched your search
@@ -13,10 +13,14 @@ name = "alknet_tty_local"
|
||||
alknet-tty = { path = "../alknet-tty" }
|
||||
portable-pty = "0.8"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tokio-util = { version = "0.7", features = ["io"] }
|
||||
bytes = "1"
|
||||
futures-core = "0.3"
|
||||
tracing = "0.1"
|
||||
thiserror = "2"
|
||||
|
||||
[dev-dependencies]
|
||||
tokio-stream = "0.1"
|
||||
|
||||
[target.'cfg(unix)'.dependencies]
|
||||
libc = "0.2"
|
||||
Reference in new issue
Block a user