Fix an infinite loop in ProtocolsHandlerSelect (#961)

This commit is contained in:
Pierre Krieger
2019-02-20 15:06:49 +01:00
committed by GitHub
parent e92c6a219b
commit e1ad88f757
2 changed files with 53 additions and 8 deletions

View File

@ -29,11 +29,37 @@ use crate::{
}
};
use futures::prelude::*;
use std::mem;
/// Wrapper around a protocol handler and ignores all further method calls once it has shut down.
#[derive(Debug, Copy, Clone)]
pub struct Fuse<TProtoHandler> {
inner: Option<TProtoHandler>,
inner: State<TProtoHandler>,
}
#[derive(Debug, Copy, Clone)]
enum State<TProtoHandler> {
Normal(TProtoHandler),
ShuttingDown(TProtoHandler),
Shutdown,
}
impl<TProtoHandler> State<TProtoHandler> {
fn as_ref(&self) -> Option<&TProtoHandler> {
match self {
State::Normal(h) => Some(h),
State::ShuttingDown(h) => Some(h),
State::Shutdown => None,
}
}
fn as_mut(&mut self) -> Option<&mut TProtoHandler> {
match self {
State::Normal(h) => Some(h),
State::ShuttingDown(h) => Some(h),
State::Shutdown => None,
}
}
}
impl<TProtoHandler> Fuse<TProtoHandler> {
@ -41,14 +67,28 @@ impl<TProtoHandler> Fuse<TProtoHandler> {
#[inline]
pub(crate) fn new(inner: TProtoHandler) -> Self {
Fuse {
inner: Some(inner),
inner: State::Normal(inner),
}
}
/// Returns true if `shutdown()` has been called in the past, or if polling has returned
/// `Shutdown` in the past.
pub fn is_shutting_down_or_shutdown(&self) -> bool {
match self.inner {
State::Normal(_) => false,
State::ShuttingDown(_) => true,
State::Shutdown => true,
}
}
/// Returns true if polling has returned `Shutdown` in the past.
#[inline]
pub fn is_shutdown(&self) -> bool {
self.inner.is_none()
if let State::Shutdown = self.inner {
true
} else {
false
}
}
}
@ -134,9 +174,14 @@ where
#[inline]
fn shutdown(&mut self) {
if let Some(inner) = self.inner.as_mut() {
inner.shutdown()
}
self.inner = match mem::replace(&mut self.inner, State::Shutdown) {
State::Normal(mut inner) => {
inner.shutdown();
State::ShuttingDown(inner)
},
s @ State::ShuttingDown(_) => s,
s @ State::Shutdown => s,
};
}
#[inline]
@ -152,7 +197,7 @@ where
};
if let Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown)) = poll {
self.inner = None;
self.inner = State::Shutdown;
}
poll

View File

@ -248,7 +248,7 @@ where
}));
},
Async::Ready(ProtocolsHandlerEvent::Shutdown) => {
if !self.proto1.is_shutdown() {
if !self.proto1.is_shutting_down_or_shutdown() {
self.proto1.shutdown();
continue;
}