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
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
Ok(None.into())
},
@@ -793,11 +803,11 @@ impl Recv {
) -> Poll<Option<HeaderMap>, proto::Error> {
match stream.pending_recv.pop_front(&mut self.buffer) {
Some(Event::Trailers(trailers)) => Ok(Some(trailers).into()),
Some(_) => {
// TODO: This is a user error. `poll_trailers` was called before
// the entire set of data frames have been consumed. What should
// we do?
panic!("poll_trailers called before data has been consumed");
Some(event) => {
// Frame is not trailers.. not ready to poll trailers yet.
stream.pending_recv.push_front(&mut self.buffer, event);
Ok(Async::NotReady)
},
None => self.schedule_recv(stream),
}

View File

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