File tree 2 files changed +37
-5
lines changed
2 files changed +37
-5
lines changed Original file line number Diff line number Diff line change @@ -42,11 +42,12 @@ type Conn struct {
42
42
closer io.Closer
43
43
client bool
44
44
45
- closeOnce sync.Once
46
- closeErrOnce sync.Once
47
- closeErr error
48
- closed chan struct {}
49
- closing * atomicInt64
45
+ closeOnce sync.Once
46
+ closeErrOnce sync.Once
47
+ closeErr error
48
+ closed chan struct {}
49
+ closing * atomicInt64
50
+ closeReceived error
50
51
51
52
// messageWriter state.
52
53
// writeMsgLock is acquired to write a data message.
@@ -339,10 +340,12 @@ func (c *Conn) handleControl(ctx context.Context, h header) error {
339
340
if err != nil {
340
341
err = fmt .Errorf ("received invalid close payload: %w" , err )
341
342
c .exportedClose (StatusProtocolError , err .Error (), false )
343
+ c .closeReceived = err
342
344
return err
343
345
}
344
346
345
347
err = fmt .Errorf ("received close: %w" , ce )
348
+ c .closeReceived = err
346
349
c .writeClose (b , err , false )
347
350
348
351
if ctx .Err () != nil {
@@ -941,6 +944,12 @@ func (c *Conn) waitClose() error {
941
944
return err
942
945
}
943
946
defer c .releaseLock (c .readLock )
947
+
948
+ if c .closeReceived != nil {
949
+ // goroutine reading just received the close.
950
+ return c .closeReceived
951
+ }
952
+
944
953
c .readerShouldLock = false
945
954
946
955
b := bpool .Get ()
Original file line number Diff line number Diff line change @@ -868,6 +868,29 @@ func TestConn(t *testing.T) {
868
868
return c .Close (websocket .StatusNormalClosure , "" )
869
869
},
870
870
},
871
+ {
872
+ // Issue #164
873
+ name : "closeHandshake_concurrentRead" ,
874
+ server : func (ctx context.Context , c * websocket.Conn ) error {
875
+ _ , _ , err := c .Read (ctx )
876
+ return assertCloseStatus (err , websocket .StatusNormalClosure )
877
+ },
878
+ client : func (ctx context.Context , c * websocket.Conn ) error {
879
+ errc := make (chan error , 1 )
880
+ go func () {
881
+ _ , _ , err := c .Read (ctx )
882
+ errc <- err
883
+ }()
884
+
885
+ err := c .Close (websocket .StatusNormalClosure , "" )
886
+ if err != nil {
887
+ return err
888
+ }
889
+
890
+ err = <- errc
891
+ return assertCloseStatus (err , websocket .StatusNormalClosure )
892
+ },
893
+ },
871
894
}
872
895
for _ , tc := range testCases {
873
896
tc := tc
You can’t perform that action at this time.
0 commit comments