From 8b1e82f31a7ecaade440b0694c0bbe5a843b48ac Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Wed, 8 Jun 2016 21:24:31 -0700 Subject: Fix shutdown deadlock Calling ::std::process::exit() from the SIGCHLD handler would sometimes deadlock some OpenGL internal shutdown procedure. To resolve this, a flag was added that can be checked with `process_should_exit`. --- src/main.rs | 10 ++++++++-- src/tty.rs | 13 ++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 7c130bc4..94cc1bc1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,6 +44,7 @@ use grid::Grid; use term::Term; use meter::Meter; use util::thread; +use tty::process_should_exit; #[derive(Debug, Eq, PartialEq, Copy, Clone, Default)] pub struct Rgb { @@ -130,7 +131,7 @@ fn main() { } let (chars_tx, chars_rx) = ::std::sync::mpsc::channel(); - thread::spawn_named("TTY Reader", move || { + let reader_thread = thread::spawn_named("TTY Reader", move || { for c in reader.chars() { let c = c.unwrap(); chars_tx.send(c).unwrap(); @@ -219,8 +220,13 @@ fn main() { window.swap_buffers().unwrap(); } + + if process_should_exit() { + break; + } } - // TODO handle child cleanup + reader_thread.join(); + println!("Goodbye"); } diff --git a/src/tty.rs b/src/tty.rs index b91cc08e..54a1a120 100644 --- a/src/tty.rs +++ b/src/tty.rs @@ -14,6 +14,13 @@ use libc::{self, winsize, c_int, c_char, pid_t, WNOHANG, WIFEXITED, WEXITSTATUS, /// Necessary to put this in static storage for `sigchld` to have access static mut PID: pid_t = 0; +/// Exit flag +/// +/// Calling exit() in the SIGCHLD handler sometimes causes opengl to deadlock, +/// and the process hangs. Instead, this flag is set, and its status can be +/// cheked via `process_should_exit`. +static mut SHOULD_EXIT: bool = false; + extern "C" fn sigchld(a: c_int) { let mut status: c_int = 0; unsafe { @@ -29,9 +36,13 @@ extern "C" fn sigchld(a: c_int) { if !WIFEXITED(status) || WEXITSTATUS(status) != 0 { die!("child finished with error '{}'\n", status); } + + SHOULD_EXIT = true; } +} - ::std::process::exit(0); +pub fn process_should_exit() -> bool { + unsafe { SHOULD_EXIT } } pub enum Error { -- cgit