Don't panic on poll_trailers called out of order. (#189)

This patch removes a panic in `poll_trailers` that is triggered if
`poll_trailers` is called before `poll_data` returns `None`.

This is done by always trying to notify the receive task when
`poll_data` returns None and there already is pending trailers.
This commit is contained in:
Carl Lerche
2017-12-19 20:05:12 -08:00
committed by GitHub
parent 1552d62e7c
commit 4cc573fa89
2 changed files with 15 additions and 7 deletions

View File

@@ -780,6 +780,16 @@ impl Recv {
// Frame is trailer // Frame is trailer
stream.pending_recv.push_front(&mut self.buffer, event); stream.pending_recv.push_front(&mut self.buffer, event);
// Notify the recv task. This is done just in case
// `poll_trailers` was called.
//
// It is very likely that `notify_recv` will just be a no-op (as
// the task will be None), so this isn't really much of a
// performance concern. It also means we don't have to track
// state to see if `poll_trailers` was called before `poll_data`
// returned `None`.
stream.notify_recv();
// No more data frames // No more data frames
Ok(None.into()) Ok(None.into())
}, },
@@ -793,11 +803,11 @@ impl Recv {
) -> Poll<Option<HeaderMap>, proto::Error> { ) -> Poll<Option<HeaderMap>, proto::Error> {
match stream.pending_recv.pop_front(&mut self.buffer) { match stream.pending_recv.pop_front(&mut self.buffer) {
Some(Event::Trailers(trailers)) => Ok(Some(trailers).into()), Some(Event::Trailers(trailers)) => Ok(Some(trailers).into()),
Some(_) => { Some(event) => {
// TODO: This is a user error. `poll_trailers` was called before // Frame is not trailers.. not ready to poll trailers yet.
// the entire set of data frames have been consumed. What should stream.pending_recv.push_front(&mut self.buffer, event);
// we do?
panic!("poll_trailers called before data has been consumed"); Ok(Async::NotReady)
}, },
None => self.schedule_recv(stream), None => self.schedule_recv(stream),
} }

View File

@@ -149,8 +149,6 @@ impl RecvStream {
} }
/// Returns received trailers. /// Returns received trailers.
///
/// This function **must** not be called until `Body::poll` returns `None`.
pub fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, ::Error> { pub fn poll_trailers(&mut self) -> Poll<Option<HeaderMap>, ::Error> {
self.inner.inner.poll_trailers().map_err(Into::into) self.inner.inner.poll_trailers().map_err(Into::into)
} }