aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Wilm <joe@jwilm.com>2016-06-08 21:24:31 -0700
committerJoe Wilm <joe@jwilm.com>2016-06-08 21:24:31 -0700
commit8b1e82f31a7ecaade440b0694c0bbe5a843b48ac (patch)
tree0fb2e4fac0183490b62a663b9ca165e7a5e4bd0f
parent8126841ed37a9cc249f646b830b3d3d48aaf4ed7 (diff)
downloadr-alacritty-8b1e82f31a7ecaade440b0694c0bbe5a843b48ac.tar.gz
r-alacritty-8b1e82f31a7ecaade440b0694c0bbe5a843b48ac.tar.bz2
r-alacritty-8b1e82f31a7ecaade440b0694c0bbe5a843b48ac.zip
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`.
-rw-r--r--src/main.rs10
-rw-r--r--src/tty.rs13
2 files changed, 20 insertions, 3 deletions
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 {