Support nonblocking mode for tty and pty

This commit is contained in:
jiangjianfeng 2025-11-06 09:16:03 +00:00 committed by Ruihan Li
parent c4ee351639
commit a41db92b4e
3 changed files with 40 additions and 32 deletions

View File

@ -80,12 +80,17 @@ impl Pollable for PtyMaster {
}
impl FileIo for PtyMaster {
fn read(&self, writer: &mut VmWriter, _status_flags: StatusFlags) -> Result<usize> {
// TODO: Add support for non-blocking mode and timeout
fn read(&self, writer: &mut VmWriter, status_flags: StatusFlags) -> Result<usize> {
// TODO: Add support for timeout.
let mut buf = vec![0u8; writer.avail().min(IO_CAPACITY)];
let read_len = self.wait_events(IoEvents::IN, None, || {
self.slave.driver().try_read(&mut buf)
})?;
let is_nonblocking = status_flags.contains(StatusFlags::O_NONBLOCK);
let read_len = if is_nonblocking {
self.slave.driver().try_read(&mut buf)?
} else {
self.wait_events(IoEvents::IN, None, || {
self.slave.driver().try_read(&mut buf)
})?
};
self.slave.driver().pollee().invalidate();
self.slave.notify_output();
@ -94,14 +99,19 @@ impl FileIo for PtyMaster {
Ok(read_len)
}
fn write(&self, reader: &mut VmReader, _status_flags: StatusFlags) -> Result<usize> {
fn write(&self, reader: &mut VmReader, status_flags: StatusFlags) -> Result<usize> {
let mut buf = vec![0u8; reader.remain().min(IO_CAPACITY)];
let write_len = reader.read_fallible(&mut buf.as_mut_slice().into())?;
// TODO: Add support for non-blocking mode and timeout
let len = self.wait_events(IoEvents::OUT, None, || {
self.slave.push_input(&buf[..write_len])
})?;
// TODO: Add support for timeout.
let is_nonblocking = status_flags.contains(StatusFlags::O_NONBLOCK);
let len = if is_nonblocking {
self.slave.push_input(&buf[..write_len])?
} else {
self.wait_events(IoEvents::OUT, None, || {
self.slave.push_input(&buf[..write_len])
})?
};
self.slave.driver().pollee().invalidate();
Ok(len)
}

View File

@ -241,17 +241,21 @@ impl<D: TtyDriver> Pollable for Tty<D> {
}
impl<D: TtyDriver> FileIo for Tty<D> {
fn read(&self, writer: &mut VmWriter, _status_flags: StatusFlags) -> Result<usize> {
fn read(&self, writer: &mut VmWriter, status_flags: StatusFlags) -> Result<usize> {
if self.driver.is_closed() {
return Ok(0);
}
self.job_control.wait_until_in_foreground()?;
// TODO: Add support for non-blocking mode and timeout
// TODO: Add support for timeout.
let mut buf = vec![0u8; writer.avail().min(IO_CAPACITY)];
let read_len =
self.wait_events(IoEvents::IN, None, || self.ldisc.lock().try_read(&mut buf))?;
let is_nonblocking = status_flags.contains(StatusFlags::O_NONBLOCK);
let read_len = if is_nonblocking {
self.ldisc.lock().try_read(&mut buf)?
} else {
self.wait_events(IoEvents::IN, None, || self.ldisc.lock().try_read(&mut buf))?
};
self.pollee.invalidate();
self.driver.notify_input();
@ -260,14 +264,19 @@ impl<D: TtyDriver> FileIo for Tty<D> {
Ok(read_len)
}
fn write(&self, reader: &mut VmReader, _status_flags: StatusFlags) -> Result<usize> {
fn write(&self, reader: &mut VmReader, status_flags: StatusFlags) -> Result<usize> {
let mut buf = vec![0u8; reader.remain().min(IO_CAPACITY)];
let write_len = reader.read_fallible(&mut buf.as_mut_slice().into())?;
// TODO: Add support for non-blocking mode and timeout
let len = self.wait_events(IoEvents::OUT, None, || {
self.driver.push_output(&buf[..write_len])
})?;
// TODO: Add support for timeout.
let is_nonblocking = status_flags.contains(StatusFlags::O_NONBLOCK);
let len = if is_nonblocking {
self.driver.push_output(&buf[..write_len])?
} else {
self.wait_events(IoEvents::OUT, None, || {
self.driver.push_output(&buf[..write_len])
})?
};
self.pollee.invalidate();
Ok(len)
}

View File

@ -1,25 +1,14 @@
PtyTrunc.Truncate
PtyTest.MasterTermiosUnchangable
PtyTest.TermiosICRNL
PtyTest.TermiosONLCR
PtyTest.TermiosIGNCR
PtyTest.TermiosINLCR
PtyTest.TermiosONOCR
PtyTest.TermiosOCRNL
PtyTest.SwitchCanonToNonCanonNewline
PtyTest.TermiosICANONNewline
PtyTest.TermiosICANONEOF
PtyTest.CanonDiscard
PtyTest.CanonMultiline
PtyTest.SimpleEcho
PtyTest.TermiosIGNCR
PtyTest.TermiosONOCR
PtyTest.VEOLTermination
PtyTest.CanonBigWrite
PtyTest.SwitchCanonToNoncanon
PtyTest.SwitchNoncanonToCanonNewlineBig
PtyTest.SwitchNoncanonToCanonNoNewline
PtyTest.SwitchNoncanonToCanonNoNewlineBig
PtyTest.NoncanonBigWrite
PtyTest.SwitchNoncanonToCanonMultiline
PtyTest.SwitchTwiceMultiline
JobControlTest.SetTTYBadArg
JobControlTest.SetTTYDifferentSession