summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorkxt <ktamas@fastmail.fm>2021-05-24 15:00:49 +0200
committerGitHub <noreply@github.com>2021-05-24 15:00:49 +0200
commit2168793dc75380a485faa4d470489d3d8baed0dc (patch)
tree3360d4aae1b08e5576ab51adef7cd58138b92670 /src
parent193331062655c4a0b79cf9433157ec8526c4b29f (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.rs36
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(())