Skip to content

Commit d312edf

Browse files
author
winters.zc
committed
fix: panic in pop_frame()
We met the panic in our production environment, so handle this panic condition before panic. stack backtrace: 0: rust_begin_unwind at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/std/src/panicking.rs:517:5 1: core::panicking::panic_fmt at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/core/src/panicking.rs:101:14 2: core::panicking::panic at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/core/src/panicking.rs:50:5 3: h2::proto::streams::flow_control::FlowControl::send_data at /build/vendor/h2/src/proto/streams/flow_control.rs:176:9 4: h2::proto::streams::prioritize::Prioritize::pop_frame::{{closure}} at /build/vendor/h2/src/proto/streams/prioritize.rs:737:33 5: tracing::span::Span::in_scope at /build/vendor/tracing/src/span.rs:982:9 6: h2::proto::streams::prioritize::Prioritize::pop_frame at /build/vendor/h2/src/proto/streams/prioritize.rs:736:29 7: h2::proto::streams::prioritize::Prioritize::poll_complete at /build/vendor/h2/src/proto/streams/prioritize.rs:497:19 8: h2::proto::streams::send::Send::poll_complete at /build/vendor/h2/src/proto/streams/send.rs:297:9 9: h2::proto::streams::streams::Inner::poll_complete at /build/vendor/h2/src/proto/streams/streams.rs:850:16 10: h2::proto::streams::streams::Streams<B,P>::poll_complete at /build/vendor/h2/src/proto/streams/streams.rs:180:9 11: h2::proto::connection::Connection<T,P,B>::poll at /build/vendor/h2/src/proto/connection.rs:253:36 12: <h2::client::Connection<T,B> as core::future::future::Future>::poll 13: ...
1 parent 07d20b1 commit d312edf

File tree

2 files changed

+21
-5
lines changed

2 files changed

+21
-5
lines changed

src/proto/streams/flow_control.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ impl FlowControl {
6161
self.window_size.as_size()
6262
}
6363

64+
/// Check if send window is available
65+
pub fn window_available(&mut self, sz: WindowSize) -> bool {
66+
self.window_size >= sz as usize
67+
}
68+
6469
/// Returns the window size available to the consumer
6570
pub fn available(&self) -> Window {
6671
self.available
@@ -173,12 +178,15 @@ impl FlowControl {
173178
self.available
174179
);
175180

176-
// Ensure that the argument is correct
177-
assert!(self.window_size >= sz as usize);
181+
// If send size is zero it's meaningless to update flow control window
182+
if sz > 0 {
183+
// Ensure that the argument is correct
184+
assert!(self.window_size >= sz as usize);
178185

179-
// Update values
180-
self.window_size -= sz;
181-
self.available -= sz;
186+
// Update values
187+
self.window_size -= sz;
188+
self.available -= sz;
189+
}
182190
}
183191
}
184192

src/proto/streams/prioritize.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,14 @@ impl Prioritize {
744744
// capacity at this point.
745745
debug_assert!(len <= self.flow.window_size());
746746

747+
// Check if the stream level window the peer knows is available. In some
748+
// scenarios, maybe the window we know is available but the window which
749+
// peer knows is not.
750+
if len > 0 && !stream.send_flow.window_available(len) {
751+
stream.pending_send.push_front(buffer, frame.into());
752+
continue;
753+
}
754+
747755
tracing::trace!(len, "sending data frame");
748756

749757
// Update the flow control

0 commit comments

Comments
 (0)