Skip to content

fix: answer a ping that arrives after our close frame - #595

Open
Mohith26 wants to merge 1 commit into
coder:masterfrom
Mohith26:fix/pong-after-close-sent
Open

Mohith26 wants to merge 1 commit into
coder:masterfrom
Mohith26:fix/pong-after-close-sent

Conversation

@Mohith26

@Mohith26 Mohith26 commented Nov 3, 2026

Copy link
Copy Markdown

Fixes #585.

Once a close frame has been sent, writeFrame returns net.ErrClosed for every opcode. If the peer sent a ping before it saw our close, waitCloseHandshake reads it, handleControl tries to write the pong, and that write fails. The error ends waitCloseHandshake before the peer's close frame is read, and Close still returns nil because the deferred check maps net.ErrClosed to nil. RFC 6455 section 5.5.2 says an endpoint must answer a ping unless it has already received a close frame, so the pong should still go out.

This allows opPong through the close-sent check in writeFrame and keeps refusing everything else. It's the change suggested in the issue.

Test: TestCloseAnswersPingBeforePeerClose uses net.Pipe and a raw peer that reads our close frame, sends a ping, expects a pong with the same payload, then sends its close frame. It fails on master (no pong) and passes with this change. go test -race ./... passes and gofmt is clean. I didn't run the autobahn suite.

I used AI assistance to write this; I ran the tests above myself.

writeFrame refused every opcode once a close frame was sent, so a ping the
peer sent before it saw our close got no pong. The failed pong write also
aborted waitCloseHandshake before the peer's close frame was read, while
Close still returned nil. RFC 6455 section 5.5.2 requires a pong until a
close frame has been received, so allow pongs after close is sent.

Fixes coder#585

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Close() aborts the closing handshake when an in-flight Ping arrives after Close is sent

1 participant