mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-12 18:01:36 +00:00
rpc: send WebSocket close frame on client disconnect (#33909)
When `rpc.Client.Close()` is called, the TCP connection is torn down without sending a WebSocket Close frame. The server sees `websocket: close 1006 (abnormal closure): unexpected EOF` instead of a clean 1000 (normal closure). ### Root cause `websocketCodec.close()` delegates to `jsonCodec.close()` which calls `c.conn.Close()` — gorilla/websocket's `Conn.Close` explicitly "[closes the underlying network connection without sending or waiting for a close message](https://pkg.go.dev/github.com/gorilla/websocket#Conn.Close)" (per RFC 6455). ### Fix Send a WebSocket Close control frame (opcode 0x8, status 1000) before closing the underlying connection. Uses `WriteControl` with the same `encMu` mutex pattern already used by `pingLoop` for write serialization, and reuses the existing `wsPingWriteTimeout` (5s) constant. `WriteControl` errors are safe to ignore — the connection may already be broken by the time we attempt the close frame. Fixes #30482
This commit is contained in:
parent
6ece4cd143
commit
33c1bd59ff
1 changed files with 10 additions and 0 deletions
|
|
@ -324,6 +324,16 @@ func newWebsocketCodec(conn *websocket.Conn, host string, req http.Header, readL
|
|||
}
|
||||
|
||||
func (wc *websocketCodec) close() {
|
||||
// Send a WebSocket Close frame before closing the underlying connection,
|
||||
// so the server sees a clean 1000 (normal closure) instead of 1006 (abnormal).
|
||||
wc.jsonCodec.encMu.Lock()
|
||||
wc.conn.WriteControl(
|
||||
websocket.CloseMessage,
|
||||
websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""),
|
||||
time.Now().Add(wsPingWriteTimeout),
|
||||
)
|
||||
wc.jsonCodec.encMu.Unlock()
|
||||
|
||||
wc.jsonCodec.close()
|
||||
wc.wg.Wait()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue