| @@ -372,7 +372,7 @@ macro_rules! conn_response { | ||||
|             } | ||||
|             None => { | ||||
|                 if let Some((key, socket)) = $scope.awaiting_slot.pop_front() { | ||||
|                     rotor_try!($scope.register(&socket, EventSet::writable(), PollOpt::level())); | ||||
|                     rotor_try!($scope.register(&socket, EventSet::writable() | EventSet::hup(), PollOpt::level())); | ||||
|                     rotor::Response::ok(ClientFsm::Connecting((key, socket))) | ||||
|                 } else { | ||||
|                     rotor::Response::done() | ||||
| @@ -460,7 +460,7 @@ where C: Connect, | ||||
|     type Seed = (C::Key, C::Output); | ||||
|  | ||||
|     fn create(seed: Self::Seed, scope: &mut Scope<Self::Context>) -> rotor::Response<Self, rotor::Void> { | ||||
|         rotor_try!(scope.register(&seed.1, EventSet::writable(), PollOpt::level())); | ||||
|         rotor_try!(scope.register(&seed.1, EventSet::writable() | EventSet::hup(), PollOpt::level())); | ||||
|         rotor::Response::ok(ClientFsm::Connecting(seed)) | ||||
|     } | ||||
|  | ||||
| @@ -483,11 +483,11 @@ where C: Connect, | ||||
|                     if let Some(err) = seed.1.take_socket_error().err() { | ||||
|                         debug!("error while connecting: {:?}", err); | ||||
|                         scope.pop_queue(&seed.0).map(move |mut queued| queued.handler.on_error(::Error::Io(err))); | ||||
|                         rotor::Response::done() | ||||
|                     } else { | ||||
|                         trace!("connecting is_error, but no socket error"); | ||||
|                         rotor::Response::ok(ClientFsm::Connecting(seed)) | ||||
|                     } | ||||
|  | ||||
|                     rotor::Response::done() | ||||
|                 } else if events.is_writable() { | ||||
|                     if scope.queue.contains_key(&seed.0) { | ||||
|                         trace!("connected and writable {:?}", seed.0); | ||||
| @@ -541,6 +541,7 @@ where C: Connect, | ||||
|  | ||||
|                 // Check all idle connections regardless of origin | ||||
|                 for (key, idle) in scope.idle_conns.iter_mut() { | ||||
|                     // Pop from the front since those are lease recently used | ||||
|                     while let Some(ctrl) = idle.pop_front() { | ||||
|                         // Signal connection to close. An err here means the | ||||
|                         // socket is already dead can should be tossed. | ||||
| @@ -667,7 +668,9 @@ where C: Connect, | ||||
|                                 let mut remove_idle = false; | ||||
|                                 let mut woke_up = false; | ||||
|                                 if let Some(mut idle) = scope.idle_conns.get_mut(&key) { | ||||
|                                     while let Some(ctrl) = idle.pop_front() { | ||||
|                                     // Pop from back since those are most recently used. Connections | ||||
|                                     // at the front are allowed to expire. | ||||
|                                     while let Some(ctrl) = idle.pop_back() { | ||||
|                                         // err means the socket has since died | ||||
|                                         if ctrl.ready(Next::write()).is_ok() { | ||||
|                                             woke_up = true; | ||||
|   | ||||
| @@ -37,6 +37,10 @@ struct ConnInner<K: Key, T: Transport, H: MessageHandler<T>> { | ||||
|     key: K, | ||||
|     state: State<H, T>, | ||||
|     transport: T, | ||||
|     /// Records a WouldBlock error when trying to read | ||||
|     /// | ||||
|     /// This flag is used to prevent busy looping | ||||
|     read_would_block: bool, | ||||
| } | ||||
|  | ||||
| impl<K: Key, T: Transport, H: MessageHandler<T>> fmt::Debug for ConnInner<K, T, H> { | ||||
| @@ -153,7 +157,10 @@ impl<K: Key, T: Transport, H: MessageHandler<T>> ConnInner<K, T, H> { | ||||
|                     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; | ||||
| @@ -236,6 +243,30 @@ impl<K: Key, T: Transport, H: MessageHandler<T>> ConnInner<K, T, H> { | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             State::Init { interest: Next_::Wait, .. } => { | ||||
|                 match self.buf.read_from(&mut self.transport) { | ||||
|                     Ok(0) => { | ||||
|                         // End-of-file; connection was closed by peer | ||||
|                         State::Closed | ||||
|                     }, | ||||
|                     Ok(n) => { | ||||
|                         // Didn't expect bytes here! Close the connection. | ||||
|                         warn!("read {} bytes in State::Init with Wait interest", n); | ||||
|                         State::Closed | ||||
|                     }, | ||||
|                     Err(e) => match e.kind() { | ||||
|                         io::ErrorKind::WouldBlock => { | ||||
|                             // This is the expected case reading in this state | ||||
|                             self.read_would_block = true; | ||||
|                             state | ||||
|                         }, | ||||
|                         _ => { | ||||
|                             warn!("socket error reading State::Init with Wait interest: {}", e); | ||||
|                             State::Closed | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|             State::Init { .. } => { | ||||
|                 trace!("on_readable State::{:?}", state); | ||||
|                 state | ||||
| @@ -265,7 +296,10 @@ impl<K: Key, T: Transport, H: MessageHandler<T>> ConnInner<K, T, H> { | ||||
|                         }, | ||||
|                         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; | ||||
| @@ -459,10 +493,15 @@ impl<K: Key, T: Transport, H: MessageHandler<T>> ConnInner<K, T, H> { | ||||
|     } | ||||
|  | ||||
|     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<F>(&mut self, err: ::Error, factory: &F) where F: MessageHandlerFactory<K, T> { | ||||
| @@ -478,6 +517,8 @@ impl<K: Key, T: Transport, H: MessageHandler<T>> ConnInner<K, T, H> { | ||||
|  | ||||
|     fn on_readable<F>(&mut self, scope: &mut Scope<F>) | ||||
|     where F: MessageHandlerFactory<K, T, Output=H> { | ||||
|         // 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); | ||||
| @@ -526,6 +567,7 @@ impl<K: Key, T: Transport, H: MessageHandler<T>> Conn<K, T, H> { | ||||
|                 timeout_start: Some(now), | ||||
|             }, | ||||
|             transport: transport, | ||||
|             read_would_block: false, | ||||
|         })) | ||||
|     } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user