From a7fc46afce5e7eb7bd44749def28773c3211cab0 Mon Sep 17 00:00:00 2001 From: Joe Wilm Date: Tue, 10 Jan 2017 10:27:25 -0800 Subject: [PATCH] Fix bug where event loop could get stuck reading One symptom of this bug was being unable to send C-c during `cat /dev/urandom`. cc #271 --- src/event_loop.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/event_loop.rs b/src/event_loop.rs index eb0b24b8..483490f0 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -163,9 +163,13 @@ impl EventLoop self.tx.clone() } - #[inline] - fn channel_event(&mut self, state: &mut State) { + // Drain the channel + // + // Returns true if items were received + fn drain_recv_channel(&self, state: &mut State) -> bool { + let mut received_item = false; while let Ok(msg) = self.rx.try_recv() { + received_item = true; match msg { Msg::Input(input) => { state.write_list.push_back(input); @@ -173,6 +177,13 @@ impl EventLoop } } + received_item + } + + #[inline] + fn channel_event(&mut self, state: &mut State) { + self.drain_recv_channel(state); + self.poll.reregister( &self.rx, CHANNEL, Ready::readable(), @@ -218,6 +229,20 @@ impl EventLoop if !terminal.dirty { self.display.notify(); terminal.dirty = true; + + // Break for writing + // + // Want to prevent case where reading always returns + // data and sequences like `C-c` cannot be sent. + // + // Doing this check in !terminal.dirty will prevent the + // condition from being checked overzealously. + if state.writing.is_some() + || !state.write_list.is_empty() + || self.drain_recv_channel(state) + { + break; + } } }, Err(err) => {