Skip to content

Commit 7de6f2b

Browse files
authored
Merge pull request #933 from jwilm/misc-client-fixes
Misc client fixes
2 parents d5df3fd + 20fac49 commit 7de6f2b

File tree

2 files changed

+54
-9
lines changed

2 files changed

+54
-9
lines changed

src/client/mod.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ macro_rules! conn_response {
372372
}
373373
None => {
374374
if let Some((key, socket)) = $scope.awaiting_slot.pop_front() {
375-
rotor_try!($scope.register(&socket, EventSet::writable(), PollOpt::level()));
375+
rotor_try!($scope.register(&socket, EventSet::writable() | EventSet::hup(), PollOpt::level()));
376376
rotor::Response::ok(ClientFsm::Connecting((key, socket)))
377377
} else {
378378
rotor::Response::done()
@@ -460,7 +460,7 @@ where C: Connect,
460460
type Seed = (C::Key, C::Output);
461461

462462
fn create(seed: Self::Seed, scope: &mut Scope<Self::Context>) -> rotor::Response<Self, rotor::Void> {
463-
rotor_try!(scope.register(&seed.1, EventSet::writable(), PollOpt::level()));
463+
rotor_try!(scope.register(&seed.1, EventSet::writable() | EventSet::hup(), PollOpt::level()));
464464
rotor::Response::ok(ClientFsm::Connecting(seed))
465465
}
466466

@@ -483,11 +483,11 @@ where C: Connect,
483483
if let Some(err) = seed.1.take_socket_error().err() {
484484
debug!("error while connecting: {:?}", err);
485485
scope.pop_queue(&seed.0).map(move |mut queued| queued.handler.on_error(::Error::Io(err)));
486-
rotor::Response::done()
487486
} else {
488487
trace!("connecting is_error, but no socket error");
489-
rotor::Response::ok(ClientFsm::Connecting(seed))
490488
}
489+
490+
rotor::Response::done()
491491
} else if events.is_writable() {
492492
if scope.queue.contains_key(&seed.0) {
493493
trace!("connected and writable {:?}", seed.0);
@@ -541,6 +541,7 @@ where C: Connect,
541541

542542
// Check all idle connections regardless of origin
543543
for (key, idle) in scope.idle_conns.iter_mut() {
544+
// Pop from the front since those are lease recently used
544545
while let Some(ctrl) = idle.pop_front() {
545546
// Signal connection to close. An err here means the
546547
// socket is already dead can should be tossed.
@@ -667,7 +668,9 @@ where C: Connect,
667668
let mut remove_idle = false;
668669
let mut woke_up = false;
669670
if let Some(mut idle) = scope.idle_conns.get_mut(&key) {
670-
while let Some(ctrl) = idle.pop_front() {
671+
// Pop from back since those are most recently used. Connections
672+
// at the front are allowed to expire.
673+
while let Some(ctrl) = idle.pop_back() {
671674
// err means the socket has since died
672675
if ctrl.ready(Next::write()).is_ok() {
673676
woke_up = true;

src/http/conn.rs

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ struct ConnInner<K: Key, T: Transport, H: MessageHandler<T>> {
3737
key: K,
3838
state: State<H, T>,
3939
transport: T,
40+
/// Records a WouldBlock error when trying to read
41+
///
42+
/// This flag is used to prevent busy looping
43+
read_would_block: bool,
4044
}
4145

4246
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> {
153157
Ok(head) => head,
154158
Err(::Error::Io(e)) => match e.kind() {
155159
io::ErrorKind::WouldBlock |
156-
io::ErrorKind::Interrupted => return state,
160+
io::ErrorKind::Interrupted => {
161+
self.read_would_block = true;
162+
return state;
163+
},
157164
_ => {
158165
debug!("io error trying to parse {:?}", e);
159166
return State::Closed;
@@ -236,6 +243,30 @@ impl<K: Key, T: Transport, H: MessageHandler<T>> ConnInner<K, T, H> {
236243
}
237244
}
238245
},
246+
State::Init { interest: Next_::Wait, .. } => {
247+
match self.buf.read_from(&mut self.transport) {
248+
Ok(0) => {
249+
// End-of-file; connection was closed by peer
250+
State::Closed
251+
},
252+
Ok(n) => {
253+
// Didn't expect bytes here! Close the connection.
254+
warn!("read {} bytes in State::Init with Wait interest", n);
255+
State::Closed
256+
},
257+
Err(e) => match e.kind() {
258+
io::ErrorKind::WouldBlock => {
259+
// This is the expected case reading in this state
260+
self.read_would_block = true;
261+
state
262+
},
263+
_ => {
264+
warn!("socket error reading State::Init with Wait interest: {}", e);
265+
State::Closed
266+
}
267+
}
268+
}
269+
},
239270
State::Init { .. } => {
240271
trace!("on_readable State::{:?}", state);
241272
state
@@ -265,7 +296,10 @@ impl<K: Key, T: Transport, H: MessageHandler<T>> ConnInner<K, T, H> {
265296
},
266297
Err(::Error::Io(e)) => match e.kind() {
267298
io::ErrorKind::WouldBlock |
268-
io::ErrorKind::Interrupted => None,
299+
io::ErrorKind::Interrupted => {
300+
self.read_would_block = true;
301+
None
302+
},
269303
_ => {
270304
debug!("io error trying to parse {:?}", e);
271305
return State::Closed;
@@ -459,10 +493,15 @@ impl<K: Key, T: Transport, H: MessageHandler<T>> ConnInner<K, T, H> {
459493
}
460494

461495
fn can_read_more(&self, was_init: bool) -> bool {
462-
match self.state {
496+
let transport_blocked = self.transport.blocked().is_some();
497+
let read_would_block = self.read_would_block;
498+
499+
let state_machine_ok = match self.state {
463500
State::Init { .. } => !was_init && !self.buf.is_empty(),
464501
_ => !self.buf.is_empty()
465-
}
502+
};
503+
504+
!transport_blocked && !read_would_block && state_machine_ok
466505
}
467506

468507
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> {
478517

479518
fn on_readable<F>(&mut self, scope: &mut Scope<F>)
480519
where F: MessageHandlerFactory<K, T, Output=H> {
520+
// Clear would_block flag so state is clear going into read
521+
self.read_would_block = false;
481522
trace!("on_readable -> {:?}", self.state);
482523
let state = mem::replace(&mut self.state, State::Closed);
483524
self.state = self.read(scope, state);
@@ -526,6 +567,7 @@ impl<K: Key, T: Transport, H: MessageHandler<T>> Conn<K, T, H> {
526567
timeout_start: Some(now),
527568
},
528569
transport: transport,
570+
read_would_block: false,
529571
}))
530572
}
531573

0 commit comments

Comments
 (0)