From d32b804759074de42bb0744d792accd5796cd4e8 Mon Sep 17 00:00:00 2001 From: "winters.zc" Date: Fri, 6 Jan 2023 12:19:41 +0800 Subject: [PATCH] fix: panic in pop_frame() We met the panic in our production environment, so handle this panic condition before panic. The 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::poll_complete at /build/vendor/h2/src/proto/streams/streams.rs:180:9 11: h2::proto::connection::Connection::poll at /build/vendor/h2/src/proto/connection.rs:253:36 12: as core::future::future::Future>::poll 13: ... --- src/proto/streams/flow_control.rs | 15 +++++++++------ src/proto/streams/prioritize.rs | 8 ++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/proto/streams/flow_control.rs b/src/proto/streams/flow_control.rs index b1b2745e..73a7754d 100644 --- a/src/proto/streams/flow_control.rs +++ b/src/proto/streams/flow_control.rs @@ -173,12 +173,15 @@ impl FlowControl { self.available ); - // Ensure that the argument is correct - assert!(self.window_size >= sz as usize); - - // Update values - self.window_size -= sz; - self.available -= sz; + // If send size is zero it's meaningless to update flow control window + if sz > 0 { + // Ensure that the argument is correct + assert!(self.window_size >= sz as usize); + + // Update values + self.window_size -= sz; + self.available -= sz; + } } } diff --git a/src/proto/streams/prioritize.rs b/src/proto/streams/prioritize.rs index 329e5502..98c4c18a 100644 --- a/src/proto/streams/prioritize.rs +++ b/src/proto/streams/prioritize.rs @@ -744,6 +744,14 @@ impl Prioritize { // capacity at this point. debug_assert!(len <= self.flow.window_size()); + // Check if the stream level window the peer knows is available. In some + // scenarios, maybe the window we know is available but the window which + // peer knows is not. + if len > 0 && len >= stream.send_flow.window_size() { + stream.pending_send.push_front(buffer, frame.into()); + continue; + } + tracing::trace!(len, "sending data frame"); // Update the flow control