Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions lib/protocol/http2/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -298,28 +298,25 @@ def receive_goaway(frame)

# Write a single frame to the connection.
# @parameter frame [Frame] The frame to write.
# @raises [EOFError] If the connection is closed.
def write_frame(frame)
synchronize do
@framer.write_frame(frame)
open_framer.write_frame(frame)
end

@framer.flush
open_framer.flush
end

# Write multiple frames within a synchronized block.
# @yields {|framer| ...} The framer for writing multiple frames.
# @parameter framer [Framer] The framer instance.
# @raises [EOFError] If the connection is closed.
def write_frames
if @framer
synchronize do
yield @framer
end

@framer.flush
else
raise EOFError, "Connection closed!"
synchronize do
yield open_framer
end

open_framer.flush
end

# Update local settings and adjust stream window capacities.
Expand Down Expand Up @@ -668,6 +665,13 @@ def receive_continuation(frame)
def receive_frame(frame)
# ignore.
end

private

# The connection is closed, and `@framer` cleared, by the task reading frames, which can happen while a writer waits for the lock or for the socket, so it is checked again at each use.
def open_framer
@framer or raise EOFError, "Connection closed!"
end
end
end
end
4 changes: 4 additions & 0 deletions releases.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Releases

## Unreleased

- `Connection#write_frame` and `#write_frames` raise `EOFError` when the connection closes while the write waits for the lock or the socket, rather than `NoMethodError` on the cleared framer.

## v0.29.1

- Sign releases with the Socketry release certificate.
Expand Down
24 changes: 24 additions & 0 deletions test/protocol/http2/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,30 @@
end.to raise_exception(EOFError, message: be =~ /Connection closed/)
end

with "a connection which closes while a write waits for the lock" do
def before
super

def connection.synchronize
close
super
end
end

it "can't write a frame" do
expect do
connection.write_frame(Protocol::HTTP2::PingFrame.new)
end.to raise_exception(EOFError, message: be =~ /Connection closed/)
end

it "can't write frames" do
expect do
connection.write_frames do |framer|
end
end.to raise_exception(EOFError, message: be =~ /Connection closed/)
end
end

with "#close" do
it "closes the connection without active streams" do
# No active streams
Expand Down