diff --git a/lib/protocol/websocket/connection.rb b/lib/protocol/websocket/connection.rb index 0632c90..ddeb9ef 100644 --- a/lib/protocol/websocket/connection.rb +++ b/lib/protocol/websocket/connection.rb @@ -104,6 +104,8 @@ def close_write(error = nil) else send_close end + rescue + @state = :closed end # Close the connection gracefully. This will send a close frame and wait for the remote end to respond with a close frame. Any data received after the close frame is sent will be ignored. If you want to process this data, use {#close_write} instead, and read the data before calling {#close}. diff --git a/releases.md b/releases.md index f72de06..ce51def 100644 --- a/releases.md +++ b/releases.md @@ -1,5 +1,9 @@ # Releases +## Unreleased + + - If `Connection#close_write` fails, the connection will now be fully closed to prevent hanging connections. + ## v0.21.0 - All frame reading and writing logic has been consolidated into `Framer` to improve performance. diff --git a/test/protocol/websocket/connection.rb b/test/protocol/websocket/connection.rb index cb83ba4..12d21b1 100644 --- a/test/protocol/websocket/connection.rb +++ b/test/protocol/websocket/connection.rb @@ -47,6 +47,43 @@ expect(connection).to be(:closed?) end + + it "does not raise if the underlying stream is closed" do + server.close + + expect do + connection.close_write + end.not.to raise_exception + + expect(connection).to be(:closed?) + end + + it "does not raise if the underlying stream is closed (with error)" do + server.close + + expect do + connection.close_write(RuntimeError.new("something went wrong")) + end.not.to raise_exception + + expect(connection).to be(:closed?) + end + + it "is not closed when close_write succeeds" do + connection.close_write + + expect(connection).not.to be(:closed?) + end + + it "can still read after a successful close_write" do + text_frame = Protocol::WebSocket::TextFrame.new(true) + text_frame.pack("Hello") + client.write_frame(text_frame) + + connection.close_write + + message = connection.read + expect(message).to be == "Hello" + end end with "#shutdown" do