diff options
Diffstat (limited to 'alacritty_terminal/src/tty/unix.rs')
-rw-r--r-- | alacritty_terminal/src/tty/unix.rs | 129 |
1 files changed, 63 insertions, 66 deletions
diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index fd99edee..4523666e 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -2,26 +2,34 @@ use std::ffi::CStr; use std::fs::File; -use std::io::{Error, ErrorKind, Result}; +use std::io::{Error, ErrorKind, Read, Result}; use std::mem::MaybeUninit; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; +use std::os::unix::net::UnixStream; use std::os::unix::process::CommandExt; use std::process::{Child, Command, Stdio}; +use std::sync::Arc; use std::{env, ptr}; use libc::{self, c_int, winsize, TIOCSCTTY}; use log::error; -use mio::unix::EventedFd; use nix::pty::openpty; #[cfg(any(target_os = "linux", target_os = "macos"))] use nix::sys::termios::{self, InputFlags, SetArg}; +use polling::{Event, PollMode, Poller}; use signal_hook::consts as sigconsts; -use signal_hook_mio::v0_6::Signals; +use signal_hook::low_level::pipe as signal_pipe; use crate::config::PtyConfig; use crate::event::{OnResize, WindowSize}; use crate::tty::{ChildEvent, EventedPty, EventedReadWrite}; +// Interest in PTY read/writes. +pub(crate) const PTY_READ_WRITE_TOKEN: usize = 0; + +// Interest in new child events. +pub(crate) const PTY_CHILD_EVENT_TOKEN: usize = 1; + macro_rules! die { ($($arg:tt)*) => {{ error!($($arg)*); @@ -103,9 +111,7 @@ fn get_pw_entry(buf: &mut [i8; 1024]) -> Result<Passwd<'_>> { pub struct Pty { child: Child, file: File, - token: mio::Token, - signals: Signals, - signals_token: mio::Token, + signals: UnixStream, } impl Pty { @@ -254,7 +260,14 @@ pub fn new(config: &PtyConfig, window_size: WindowSize, window_id: u64) -> Resul } // Prepare signal handling before spawning child. - let signals = Signals::new([sigconsts::SIGCHLD]).expect("error preparing signal handling"); + let signals = { + let (sender, recv) = UnixStream::pair()?; + + // Register the recv end of the pipe for SIGCHLD. + signal_pipe::register(sigconsts::SIGCHLD, sender)?; + recv.set_nonblocking(true)?; + recv + }; match builder.spawn() { Ok(child) => { @@ -264,13 +277,7 @@ pub fn new(config: &PtyConfig, window_size: WindowSize, window_id: u64) -> Resul set_nonblocking(master); } - let mut pty = Pty { - child, - file: unsafe { File::from_raw_fd(master) }, - token: mio::Token::from(0), - signals, - signals_token: mio::Token::from(0), - }; + let mut pty = Pty { child, file: unsafe { File::from_raw_fd(master) }, signals }; pty.on_resize(window_size); Ok(pty) }, @@ -300,46 +307,47 @@ impl EventedReadWrite for Pty { type Writer = File; #[inline] - fn register( + unsafe fn register( &mut self, - poll: &mio::Poll, - token: &mut dyn Iterator<Item = mio::Token>, - interest: mio::Ready, - poll_opts: mio::PollOpt, + poll: &Arc<Poller>, + mut interest: Event, + poll_opts: PollMode, ) -> Result<()> { - self.token = token.next().unwrap(); - poll.register(&EventedFd(&self.file.as_raw_fd()), self.token, interest, poll_opts)?; + interest.key = PTY_READ_WRITE_TOKEN; + unsafe { + poll.add_with_mode(&self.file, interest, poll_opts)?; + } - self.signals_token = token.next().unwrap(); - poll.register( - &self.signals, - self.signals_token, - mio::Ready::readable(), - mio::PollOpt::level(), - ) + unsafe { + poll.add_with_mode( + &self.signals, + Event::readable(PTY_CHILD_EVENT_TOKEN), + PollMode::Level, + ) + } } #[inline] fn reregister( &mut self, - poll: &mio::Poll, - interest: mio::Ready, - poll_opts: mio::PollOpt, + poll: &Arc<Poller>, + mut interest: Event, + poll_opts: PollMode, ) -> Result<()> { - poll.reregister(&EventedFd(&self.file.as_raw_fd()), self.token, interest, poll_opts)?; + interest.key = PTY_READ_WRITE_TOKEN; + poll.modify_with_mode(&self.file, interest, poll_opts)?; - poll.reregister( + poll.modify_with_mode( &self.signals, - self.signals_token, - mio::Ready::readable(), - mio::PollOpt::level(), + Event::readable(PTY_CHILD_EVENT_TOKEN), + PollMode::Level, ) } #[inline] - fn deregister(&mut self, poll: &mio::Poll) -> Result<()> { - poll.deregister(&EventedFd(&self.file.as_raw_fd()))?; - poll.deregister(&self.signals) + fn deregister(&mut self, poll: &Arc<Poller>) -> Result<()> { + poll.delete(&self.file)?; + poll.delete(&self.signals) } #[inline] @@ -348,43 +356,32 @@ impl EventedReadWrite for Pty { } #[inline] - fn read_token(&self) -> mio::Token { - self.token - } - - #[inline] fn writer(&mut self) -> &mut File { &mut self.file } - - #[inline] - fn write_token(&self) -> mio::Token { - self.token - } } impl EventedPty for Pty { #[inline] fn next_child_event(&mut self) -> Option<ChildEvent> { - self.signals.pending().next().and_then(|signal| { - if signal != sigconsts::SIGCHLD { - return None; - } - - match self.child.try_wait() { - Err(e) => { - error!("Error checking child process termination: {}", e); - None - }, - Ok(None) => None, - Ok(_) => Some(ChildEvent::Exited), + // See if there has been a SIGCHLD. + let mut buf = [0u8; 1]; + if let Err(err) = self.signals.read(&mut buf) { + if err.kind() != ErrorKind::WouldBlock { + error!("Error reading from signal pipe: {}", err); } - }) - } + return None; + } - #[inline] - fn child_event_token(&self) -> mio::Token { - self.signals_token + // Match on the child process. + match self.child.try_wait() { + Err(err) => { + error!("Error checking child process termination: {}", err); + None + }, + Ok(None) => None, + Ok(_) => Some(ChildEvent::Exited), + } } } |