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

View File

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

View File

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