mirror of
https://github.com/wez/wezterm.git
synced 2024-12-28 07:55:03 +03:00
simplify child waiting
This commit is contained in:
parent
c9c5b25b01
commit
ac7d2a9cda
@ -433,6 +433,8 @@ impl TerminalWindow {
|
||||
}
|
||||
Err(TryRecvError::Disconnected) => bail!("clipboard thread died"),
|
||||
}
|
||||
|
||||
self.test_for_child_exit()?;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
10
src/main.rs
10
src/main.rs
@ -81,10 +81,8 @@ fn run_glium(
|
||||
let poll = Poll::new()?;
|
||||
poll.register(&master, Token(0), Ready::readable(), PollOpt::edge())?;
|
||||
|
||||
let waiter = sigchld::ChildWaiter::new()?;
|
||||
poll.register(&waiter, Token(2), Ready::readable(), PollOpt::edge())?;
|
||||
|
||||
let mut events_loop = glium::glutin::EventsLoop::new();
|
||||
sigchld::activate(events_loop.create_proxy())?;
|
||||
|
||||
let mut window = gliumwindows::TerminalWindow::new(
|
||||
&events_loop,
|
||||
@ -113,12 +111,6 @@ fn run_glium(
|
||||
if event.token() == Token(0) && event.readiness().is_readable() {
|
||||
window.handle_pty_readable_event()?;
|
||||
}
|
||||
if event.token() == Token(2) {
|
||||
println!("sigchld ready");
|
||||
let pid = waiter.read_one()?;
|
||||
println!("got sigchld from pid {}", pid);
|
||||
window.test_for_child_exit()?;
|
||||
}
|
||||
}
|
||||
} else if window.need_paint() {
|
||||
window.paint()?;
|
||||
|
141
src/sigchld.rs
141
src/sigchld.rs
@ -1,142 +1,37 @@
|
||||
//! Helper for detecting SIGCHLD
|
||||
|
||||
use failure::Error;
|
||||
use glium::glutin::EventsLoopProxy;
|
||||
use libc;
|
||||
use mio::{Poll, PollOpt, Ready, Token};
|
||||
use mio::event::Evented;
|
||||
use mio::unix::EventedFd;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::ptr;
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
static mut WRITE_END: RawFd = -1;
|
||||
static mut EVENT_LOOP: Option<EventsLoopProxy> = None;
|
||||
|
||||
pub struct ChildWaiter {
|
||||
fd: RawFd,
|
||||
}
|
||||
|
||||
impl Drop for ChildWaiter {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
libc::close(self.fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
extern "C" fn chld_handler(_signo: libc::c_int, si: *const libc::siginfo_t, _: *const u8) {
|
||||
extern "C" fn chld_handler(_signo: libc::c_int, _si: *const libc::siginfo_t, _: *const u8) {
|
||||
unsafe {
|
||||
let pid = (*si).si_pid;
|
||||
libc::write(
|
||||
WRITE_END,
|
||||
&pid as *const _ as *const libc::c_void,
|
||||
mem::size_of::<libc::pid_t>(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl ChildWaiter {
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub fn new() -> Result<ChildWaiter, Error> {
|
||||
unsafe {
|
||||
let mut pipe: [RawFd; 2] = [-1, -1];
|
||||
let res = libc::pipe(pipe.as_mut_ptr());
|
||||
if res == -1 {
|
||||
bail!("pipe failed: {:?}", io::Error::last_os_error());
|
||||
match EVENT_LOOP.as_mut() {
|
||||
Some(proxy) => {
|
||||
proxy.wakeup().ok();
|
||||
}
|
||||
|
||||
WRITE_END = pipe[1];
|
||||
|
||||
let mut sa: libc::sigaction = mem::zeroed();
|
||||
sa.sa_sigaction = chld_handler as usize;
|
||||
sa.sa_flags = (libc::SA_SIGINFO | libc::SA_RESTART | libc::SA_NOCLDSTOP) as _;
|
||||
let res = libc::sigaction(libc::SIGCHLD, &sa, ptr::null_mut());
|
||||
if res == -1 {
|
||||
bail!("sigaction SIGCHLD failed: {:?}", io::Error::last_os_error());
|
||||
}
|
||||
|
||||
Ok(Self { fd: pipe[0] })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn new() -> Result<ChildWaiter, Error> {
|
||||
unsafe {
|
||||
let mut mask: libc::sigset_t = mem::zeroed();
|
||||
libc::sigaddset(&mut mask, libc::SIGCHLD);
|
||||
let res = libc::sigprocmask(libc::SIG_BLOCK, &mut mask, ptr::null_mut());
|
||||
if res == -1 {
|
||||
bail!(
|
||||
"sigprocmask BLOCK SIGCHLD failed: {:?}",
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
|
||||
let fd = libc::signalfd(-1, &mask, libc::SFD_NONBLOCK | libc::SFD_CLOEXEC);
|
||||
if fd == -1 {
|
||||
bail!("signalfd SIGCHLD failed: {:?}", io::Error::last_os_error());
|
||||
}
|
||||
|
||||
Ok(ChildWaiter { fd })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
pub fn read_one(&self) -> Result<u32, Error> {
|
||||
let mut pid: libc::pid_t = 0;
|
||||
let res = unsafe {
|
||||
libc::read(
|
||||
self.fd,
|
||||
&mut pid as *mut _ as *mut libc::c_void,
|
||||
mem::size_of::<libc::pid_t>(),
|
||||
)
|
||||
};
|
||||
if res == mem::size_of::<libc::pid_t>() as isize {
|
||||
Ok(pid as u32)
|
||||
} else {
|
||||
bail!("signalfd read failed: {:?}", io::Error::last_os_error());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn read_one(&self) -> Result<u32, Error> {
|
||||
const BUFSIZE: usize = mem::size_of::<libc::signalfd_siginfo>();
|
||||
let mut buf = [0u8; BUFSIZE];
|
||||
let res = unsafe { libc::read(self.fd, buf.as_mut_ptr() as *mut _, buf.len()) };
|
||||
if res == BUFSIZE as isize {
|
||||
let siginfo: libc::signalfd_siginfo = unsafe { mem::transmute(buf) };
|
||||
Ok(siginfo.ssi_pid)
|
||||
} else {
|
||||
bail!("signalfd read failed: {:?}", io::Error::last_os_error());
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Glue for working with mio
|
||||
impl Evented for ChildWaiter {
|
||||
fn register(
|
||||
&self,
|
||||
poll: &Poll,
|
||||
token: Token,
|
||||
interest: Ready,
|
||||
opts: PollOpt,
|
||||
) -> io::Result<()> {
|
||||
EventedFd(&self.fd).register(poll, token, interest, opts)
|
||||
}
|
||||
pub fn activate(proxy: EventsLoopProxy) -> Result<(), Error> {
|
||||
unsafe {
|
||||
EVENT_LOOP = Some(proxy);
|
||||
|
||||
fn reregister(
|
||||
&self,
|
||||
poll: &Poll,
|
||||
token: Token,
|
||||
interest: Ready,
|
||||
opts: PollOpt,
|
||||
) -> io::Result<()> {
|
||||
EventedFd(&self.fd).reregister(poll, token, interest, opts)
|
||||
}
|
||||
let mut sa: libc::sigaction = mem::zeroed();
|
||||
sa.sa_sigaction = chld_handler as usize;
|
||||
sa.sa_flags = (libc::SA_SIGINFO | libc::SA_RESTART | libc::SA_NOCLDSTOP) as _;
|
||||
let res = libc::sigaction(libc::SIGCHLD, &sa, ptr::null_mut());
|
||||
if res == -1 {
|
||||
bail!("sigaction SIGCHLD failed: {:?}", io::Error::last_os_error());
|
||||
}
|
||||
|
||||
fn deregister(&self, poll: &Poll) -> io::Result<()> {
|
||||
EventedFd(&self.fd).deregister(poll)
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user