diff --git a/pty/examples/whoami.rs b/pty/examples/whoami.rs index 7567db488..f7e9cca0b 100644 --- a/pty/examples/whoami.rs +++ b/pty/examples/whoami.rs @@ -24,6 +24,19 @@ fn main() { // that we've spawned the child. drop(pair.slave); + // Read the output in another thread. + // This is important because it is easy to encounter a situation + // where read/write buffers fill and block either your process + // or the spawned process. + let (tx, rx) = channel(); + let mut reader = pair.master.try_clone_reader().unwrap(); + std::thread::spawn(move || { + // Consume the output from the child + let mut s = String::new(); + reader.read_to_string(&mut s).unwrap(); + tx.send(s).unwrap(); + }); + { // Obtain the writer. // When the writer is dropped, EOF will be sent to @@ -33,6 +46,19 @@ fn main() { // generated, otherwise you risk deadlocking yourself. let mut writer = pair.master.take_writer().unwrap(); + if cfg!(target_os = "macos") { + // macOS quirk: the child and reader must be started and + // allowed a brief grace period to run before we allow + // the writer to drop. Otherwise, the data we send to + // the kernel to trigger EOF is interleaved with the + // data read by the reader! WTF!? + // This appears to be a race condition for very short + // lived processes on macOS. + // I'd love to find a more deterministic solution to + // this than sleeping. + std::thread::sleep(std::time::Duration::from_millis(20)); + } + // This example doesn't need to write anything, but if you // want to send data to the child, you'd set `to_write` to // that data and do it like this: @@ -46,19 +72,6 @@ fn main() { } } - // Read the output in another thread. - // This is important because it is easy to encounter a situation - // where read/write buffers fill and block either your process - // or the spawned process. - let (tx, rx) = channel(); - let mut reader = pair.master.try_clone_reader().unwrap(); - std::thread::spawn(move || { - // Consume the output from the child - let mut s = String::new(); - reader.read_to_string(&mut s).unwrap(); - tx.send(s).unwrap(); - }); - // Wait for the child to complete println!("child status: {:?}", child.wait().unwrap()); diff --git a/pty/src/unix.rs b/pty/src/unix.rs index 5a1cd1081..6e24cd5f5 100644 --- a/pty/src/unix.rs +++ b/pty/src/unix.rs @@ -346,7 +346,7 @@ impl Drop for UnixMasterWriter { // we send a newline followed by EOF. let eot = t.c_cc[libc::VEOF]; if eot != 0 { - let _ = self.fd.0.write_all(&[b'\r', b'\n', eot]); + let _ = self.fd.0.write_all(&[b'\n', eot]); } } }