diff options
author | kxt <ktamas@fastmail.fm> | 2021-05-24 15:00:49 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-24 15:00:49 +0200 |
commit | 2168793dc75380a485faa4d470489d3d8baed0dc (patch) | |
tree | 3360d4aae1b08e5576ab51adef7cd58138b92670 /src | |
parent | 193331062655c4a0b79cf9433157ec8526c4b29f (diff) |
fix(pty): use async io to avoid polling (#523)
This patch fixes #509 by using async read instead of polling a
non-blocking fd. This reduces CPU usage when the ptys are idle.
Diffstat (limited to 'src')
-rw-r--r-- | src/tests/fakes.rs | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/src/tests/fakes.rs b/src/tests/fakes.rs index e9042ed73..a2f338ba6 100644 --- a/src/tests/fakes.rs +++ b/src/tests/fakes.rs @@ -10,9 +10,10 @@ use zellij_utils::{nix, zellij_tile}; use crate::tests::possible_tty_inputs::{get_possible_tty_inputs, Bytes}; use crate::tests::utils::commands::{QUIT, SLEEP}; use zellij_client::os_input_output::ClientOsApi; -use zellij_server::os_input_output::{Pid, ServerOsApi}; +use zellij_server::os_input_output::{async_trait, AsyncReader, Pid, ServerOsApi}; use zellij_tile::data::Palette; use zellij_utils::{ + async_std, channels::{ChannelWithContext, SenderType, SenderWithContext}, errors::ErrorContext, interprocess::local_socket::LocalSocketStream, @@ -227,6 +228,33 @@ impl ClientOsApi for FakeInputOutput { } } +struct FakeAsyncReader { + fd: RawFd, + os_api: Box<dyn ServerOsApi>, +} + +#[async_trait] +impl AsyncReader for FakeAsyncReader { + async fn read(&mut self, buf: &mut [u8]) -> Result<usize, std::io::Error> { + // simulates async semantics: EAGAIN is not propagated to caller + loop { + let res = self.os_api.read_from_tty_stdout(self.fd, buf); + match res { + Err(nix::Error::Sys(nix::errno::Errno::EAGAIN)) => { + async_std::task::sleep(Duration::from_millis(10)).await; + continue; + } + Err(e) => { + break Err(std::io::Error::from_raw_os_error( + e.as_errno().unwrap() as i32 + )) + } + Ok(n_bytes) => break Ok(n_bytes), + } + } + } +} + impl ServerOsApi for FakeInputOutput { fn set_terminal_size_using_fd(&self, pid: RawFd, cols: u16, rows: u16) { let terminal_input = self @@ -277,6 +305,12 @@ impl ServerOsApi for FakeInputOutput { None => Err(nix::Error::Sys(nix::errno::Errno::EAGAIN)), } } + fn async_file_reader(&self, fd: RawFd) -> Box<dyn AsyncReader> { + Box::new(FakeAsyncReader { + fd, + os_api: ServerOsApi::box_clone(self), + }) + } fn tcdrain(&self, pid: RawFd) -> Result<(), nix::Error> { self.io_events.lock().unwrap().push(IoEvent::TcDrain(pid)); Ok(()) |