diff --git a/lib/async/http/protocol/http2/output.rb b/lib/async/http/protocol/http2/output.rb index 5320068..ea7019a 100644 --- a/lib/async/http/protocol/http2/output.rb +++ b/lib/async/http/protocol/http2/output.rb @@ -135,7 +135,7 @@ def passthrough(task) # chunk.clear unless chunk.frozen? # GC.start end - rescue => error + rescue Async::Cancel, StandardError => error raise ensure # Ensure the body we are reading from is fully closed: diff --git a/test/async/http/protocol/http2/output.rb b/test/async/http/protocol/http2/output.rb new file mode 100644 index 0000000..676affc --- /dev/null +++ b/test/async/http/protocol/http2/output.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +# Released under the MIT License. +# Copyright, 2026, by Tavian Barnes. + +require "async/http/protocol/http2/output" +require "async/http/body/writable" + +require "sus/fixtures/async" + +describe Async::HTTP::Protocol::HTTP2::Output do + include Sus::Fixtures::Async::ReactorContext + + let(:stream) do + Class.new do + def initialize + @errors = [] + end + + attr :errors + + def finish_output(error = nil) + @errors << error + end + end.new + end + + let(:body) {Async::HTTP::Body::Writable.new} + + let(:output) {subject.new(stream, body)} + + it "propagates cancellation when the task is cancelled" do + task = output.start + + task.cancel + task.wait + + expect(stream.errors.size).to be == 1 + expect(stream.errors.first).to be_a(Async::Cancel) + end +end