diff --git a/src/http/conn.rs b/src/http/conn.rs index c7b57581..05792d5c 100644 --- a/src/http/conn.rs +++ b/src/http/conn.rs @@ -37,6 +37,10 @@ struct ConnInner> { key: K, state: State, transport: T, + /// Records a WouldBlock error when trying to read + /// + /// This flag is used to prevent busy looping + read_would_block: bool, } impl> fmt::Debug for ConnInner { @@ -153,7 +157,10 @@ impl> ConnInner { Ok(head) => head, Err(::Error::Io(e)) => match e.kind() { io::ErrorKind::WouldBlock | - io::ErrorKind::Interrupted => return state, + io::ErrorKind::Interrupted => { + self.read_would_block = true; + return state; + }, _ => { debug!("io error trying to parse {:?}", e); return State::Closed; @@ -250,6 +257,7 @@ impl> ConnInner { Err(e) => match e.kind() { io::ErrorKind::WouldBlock => { // This is the expected case reading in this state + self.read_would_block = true; state }, _ => { @@ -288,7 +296,10 @@ impl> ConnInner { }, Err(::Error::Io(e)) => match e.kind() { io::ErrorKind::WouldBlock | - io::ErrorKind::Interrupted => None, + io::ErrorKind::Interrupted => { + self.read_would_block = true; + None + }, _ => { debug!("io error trying to parse {:?}", e); return State::Closed; @@ -482,10 +493,15 @@ impl> ConnInner { } fn can_read_more(&self, was_init: bool) -> bool { - match self.state { + let transport_blocked = self.transport.blocked().is_some(); + let read_would_block = self.read_would_block; + + let state_machine_ok = match self.state { State::Init { .. } => !was_init && !self.buf.is_empty(), _ => !self.buf.is_empty() - } + }; + + !transport_blocked && !read_would_block && state_machine_ok } fn on_error(&mut self, err: ::Error, factory: &F) where F: MessageHandlerFactory { @@ -501,6 +517,8 @@ impl> ConnInner { fn on_readable(&mut self, scope: &mut Scope) where F: MessageHandlerFactory { + // Clear would_block flag so state is clear going into read + self.read_would_block = false; trace!("on_readable -> {:?}", self.state); let state = mem::replace(&mut self.state, State::Closed); self.state = self.read(scope, state); @@ -549,6 +567,7 @@ impl> Conn { timeout_start: Some(now), }, transport: transport, + read_would_block: false, })) }