Skip to content

Commit a856e5e

Browse files
bhallionOhbibinhooyr
authored andcommitted
read.go: Avoid handling ping after close frame has been sent
Closes #298
1 parent 8abed3a commit a856e5e

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

conn_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -553,3 +553,26 @@ func assertClose(tb testing.TB, c *websocket.Conn) {
553553
err := c.Close(websocket.StatusNormalClosure, "")
554554
assert.Success(tb, err)
555555
}
556+
557+
func TestConcurrentClosePing(t *testing.T) {
558+
t.Parallel()
559+
for i := 0; i < 999; i++ {
560+
func() {
561+
c1, c2 := wstest.Pipe(nil, nil)
562+
defer c1.CloseNow()
563+
defer c2.CloseNow()
564+
c1.CloseRead(context.Background())
565+
c2.CloseRead(context.Background())
566+
go func() {
567+
for range time.Tick(time.Millisecond) {
568+
if err := c1.Ping(context.Background()); err != nil {
569+
return
570+
}
571+
}
572+
}()
573+
574+
time.Sleep(30 * time.Millisecond)
575+
assert.Success(t, c1.Close(websocket.StatusNormalClosure, ""))
576+
}()
577+
}
578+
}

read.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
//go:build !js
21
// +build !js
32

43
package websocket
@@ -287,6 +286,13 @@ func (c *Conn) handleControl(ctx context.Context, h header) (err error) {
287286

288287
switch h.opcode {
289288
case opPing:
289+
c.closeMu.Lock()
290+
wroteClose := c.wroteClose
291+
c.closeMu.Unlock()
292+
if wroteClose {
293+
// Cannot respond to ping with a pong because we already sent a close frame.
294+
return nil
295+
}
290296
return c.writeControl(ctx, opPong, b)
291297
case opPong:
292298
c.activePingsMu.Lock()

0 commit comments

Comments
 (0)