Skip to content

Commit c5ea06d

Browse files
committed
Ignore write error when echoing close frame
Closes #109
1 parent c261d49 commit c5ea06d

File tree

2 files changed

+17
-6
lines changed

2 files changed

+17
-6
lines changed

ci/test.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ if [[ $CI ]]; then
1717
pip install -qqq autobahntestsuite
1818
fi
1919

20-
go test -race -coverprofile=ci/out/coverage.prof --vet=off -bench=. -coverpkg=./... ./...
20+
go test -race -coverprofile=ci/out/coverage.prof --vet=off -bench=. -coverpkg=./... "$@" ./...
2121
go tool cover -func=ci/out/coverage.prof
2222

2323
if [[ $CI ]]; then

websocket.go

+16-5
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ type Conn struct {
4141
closer io.Closer
4242
client bool
4343

44-
closeOnce sync.Once
45-
closeErr error
46-
closed chan struct{}
44+
closeOnce sync.Once
45+
closeErrOnce sync.Once
46+
closeErr error
47+
closed chan struct{}
4748

4849
// writeMsgLock is acquired to write a data message.
4950
writeMsgLock chan struct{}
@@ -115,11 +116,17 @@ func (c *Conn) Subprotocol() string {
115116
return c.subprotocol
116117
}
117118

119+
func (c *Conn) setCloseErr(err error) {
120+
c.closeErrOnce.Do(func() {
121+
c.closeErr = xerrors.Errorf("websocket closed: %w", err)
122+
})
123+
}
124+
118125
func (c *Conn) close(err error) {
119126
c.closeOnce.Do(func() {
120127
runtime.SetFinalizer(c, nil)
121128

122-
c.closeErr = xerrors.Errorf("websocket closed: %w", err)
129+
c.setCloseErr(err)
123130
close(c.closed)
124131

125132
// Have to close after c.closed is closed to ensure any goroutine that wakes up
@@ -304,7 +311,11 @@ func (c *Conn) handleControl(ctx context.Context, h header) error {
304311
c.Close(StatusProtocolError, "received invalid close payload")
305312
return xerrors.Errorf("received invalid close payload: %w", err)
306313
}
307-
c.writeClose(b, xerrors.Errorf("received close frame: %w", ce))
314+
// This ensures the closeErr of the Conn is always the received CloseError
315+
// in case the echo close frame write fails.
316+
// See https://github.com/nhooyr/websocket/issues/109
317+
c.setCloseErr(xerrors.Errorf("received close frame: %w", ce))
318+
c.writeClose(b, nil)
308319
return c.closeErr
309320
default:
310321
panic(fmt.Sprintf("websocket: unexpected control opcode: %#v", h))

0 commit comments

Comments
 (0)