mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-23 14:51:34 +00:00
Fix an infinite loop in ProtocolsHandlerSelect (#961)
This commit is contained in:
@ -29,11 +29,37 @@ use crate::{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
/// Wrapper around a protocol handler and ignores all further method calls once it has shut down.
|
/// Wrapper around a protocol handler and ignores all further method calls once it has shut down.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Fuse<TProtoHandler> {
|
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> {
|
impl<TProtoHandler> Fuse<TProtoHandler> {
|
||||||
@ -41,14 +67,28 @@ impl<TProtoHandler> Fuse<TProtoHandler> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn new(inner: TProtoHandler) -> Self {
|
pub(crate) fn new(inner: TProtoHandler) -> Self {
|
||||||
Fuse {
|
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.
|
/// Returns true if polling has returned `Shutdown` in the past.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_shutdown(&self) -> bool {
|
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]
|
#[inline]
|
||||||
fn shutdown(&mut self) {
|
fn shutdown(&mut self) {
|
||||||
if let Some(inner) = self.inner.as_mut() {
|
self.inner = match mem::replace(&mut self.inner, State::Shutdown) {
|
||||||
inner.shutdown()
|
State::Normal(mut inner) => {
|
||||||
}
|
inner.shutdown();
|
||||||
|
State::ShuttingDown(inner)
|
||||||
|
},
|
||||||
|
s @ State::ShuttingDown(_) => s,
|
||||||
|
s @ State::Shutdown => s,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -152,7 +197,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown)) = poll {
|
if let Ok(Async::Ready(ProtocolsHandlerEvent::Shutdown)) = poll {
|
||||||
self.inner = None;
|
self.inner = State::Shutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
poll
|
poll
|
||||||
|
@ -248,7 +248,7 @@ where
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
Async::Ready(ProtocolsHandlerEvent::Shutdown) => {
|
Async::Ready(ProtocolsHandlerEvent::Shutdown) => {
|
||||||
if !self.proto1.is_shutdown() {
|
if !self.proto1.is_shutting_down_or_shutdown() {
|
||||||
self.proto1.shutdown();
|
self.proto1.shutdown();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user