8000 fix closenow race by alixander · Pull Request #427 · coder/websocket · GitHub
[go: up one dir, main page]

Skip to content

fix closenow race #427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
ws_js: Update to match new close code
  • Loading branch information
nhooyr committed Apr 7, 2024
commit 856e371494bab94984371763f53f114b4cef3547
5 changes: 3 additions & 2 deletions read.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ func (c *Conn) Read(ctx context.Context) (MessageType, []byte, error) {
// This function is idempotent.
func (c *Conn) CloseRead(ctx context.Context) context.Context {
c.closeReadMu.Lock()
if c.closeReadCtx != nil {
ctx2 := c.closeReadCtx
if ctx2 != nil {
c.closeReadMu.Unlock()
return c.closeReadCtx
return ctx2
}
ctx, cancel := context.WithCancel(ctx)
c.closeReadCtx = ctx
Expand Down
25 changes: 17 additions & 8 deletions ws_js.go
690C
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ type Conn struct {
// read limit for a message in bytes.
msgReadLimit xsync.Int64

wg sync.WaitGroup
closeReadMu sync.Mutex
closeReadCtx context.Context

closingMu sync.Mutex
isReadClosed xsync.Int64
closeOnce sync.Once
closed chan struct{}
closeErrOnce sync.Once
Expand Down Expand Up @@ -130,7 +131,10 @@ func (c *Conn) closeWithInternal() {
// Read attempts to read a message from the connection.
// The maximum time spent waiting is bounded by the context.
func (c *Conn) Read(ctx context.Context) (MessageType, []byte, error) {
if c.isReadClosed.Load() == 1 {
c.closeReadMu.Lock()
closedRead := c.closeReadCtx != nil
c.closeReadMu.Unlock()
if closedRead {
return 0, nil, errors.New("WebSocket connection read closed")
}

Expand Down Expand Up @@ -387,14 +391,19 @@ func (w *writer) Close() error {

// CloseRead implements *Conn.CloseRead for wasm.
func (c *Conn) CloseRead(ctx context.Context) context.Context {
c.isReadClosed.Store(1)

c.closeReadMu.Lock()
ctx2 := c.closeReadCtx
if ctx2 != nil {
c.closeReadMu.Unlock()
return ctx2
}
ctx, cancel := context.WithCancel(ctx)
c.wg.Add(1)
c.closeReadCtx = ctx
c.closeReadMu.Unlock()

go func() {
defer c.CloseNow()
defer c.wg.Done()
defer cancel()
defer c.CloseNow()
_, _, err := c.read(ctx)
if err != nil {
c.Close(StatusPolicyViolation, "unexpected data message")
Expand Down
0