Skip to content

Commit efd5014

Browse files
committed
change final loop to loop until a blocking condition would occur
1 parent 05ef39e commit efd5014

File tree

4 files changed

+25
-9
lines changed

4 files changed

+25
-9
lines changed

src/exec/use_pty/parent.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ pub(in crate::exec) fn exec_pty(
235235
// FIXME (ogsudo): Retry if `/dev/tty` is revoked.
236236

237237
// Flush the terminal
238+
closure.tty_pipe.right().set_nonblocking()?;
238239
closure.tty_pipe.flush_left().ok();
239240

240241
// Restore the terminal settings

src/exec/use_pty/pipe/mod.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,20 +104,19 @@ impl<L: Read + Write + AsFd, R: Read + Write + AsFd> Pipe<L, R> {
104104
let source = &mut self.right;
105105
let sink = &mut self.left;
106106

107-
// Remove bytes from the right buffer and write them to the left buffer;
108-
// then flush the left buffer.
107+
// Flush the ring buffer, then process any eventual bytes still in-flight.
108+
buffer.internal.remove(sink)?;
109109

110110
if buffer.write_handle.is_active() {
111-
// There may still be data in flight, read until EOF
111+
let mut buf = [0u8; RingBuffer::LEN];
112112
loop {
113-
buffer.internal.remove(sink)?;
114-
buffer.internal.insert(source)?;
115-
if !buffer.internal.is_full() {
116-
break;
113+
match source.read(&mut buf) {
114+
Ok(read_bytes) => sink.write_all(&buf[..read_bytes])?,
115+
Err(e) if e.kind() == io::ErrorKind::WouldBlock => break,
116+
Err(e) => return Err(e),
117117
}
118118
}
119119
}
120-
buffer.internal.remove(sink)?;
121120

122121
sink.flush()
123122
}

src/exec/use_pty/pipe/ring_buffer.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub(super) struct RingBuffer {
1010

1111
impl RingBuffer {
1212
/// The size of the internal storage of the ring buffer.
13-
const LEN: usize = 8 * 1024;
13+
pub(super) const LEN: usize = 8 * 1024;
1414

1515
/// Create a new, empty buffer.
1616
pub(super) fn new() -> Self {

src/system/term/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,22 @@ impl PtyLeader {
9797

9898
Ok(())
9999
}
100+
101+
pub(crate) fn set_nonblocking(&self) -> io::Result<()> {
102+
let fd = self.file.as_fd();
103+
// SAFETY: these two calls to fcntl are memory safe (and the file descriptor is valid as well)
104+
unsafe {
105+
let flags = cerr(libc::fcntl(fd.as_raw_fd(), libc::F_GETFL))?;
106+
107+
// Set the O_NONBLOCK flag
108+
cerr(libc::fcntl(
109+
fd.as_raw_fd(),
110+
libc::F_SETFL,
111+
flags | libc::O_NONBLOCK,
112+
))?;
113+
}
114+
Ok(())
115+
}
100116
}
101117

102118
impl io::Read for PtyLeader {

0 commit comments

Comments
 (0)