Skip to content

Race condition #168

@andersfylling

Description

@andersfylling

version 1.7.2, Go 1.3

It seems a race is triggered when calling close and waiting for a read: https://github.com/andersfylling/disgord/commit/d57507037a8b0f9d506d8940c99066e55f8ceecf/checks?check_suite_id=293975922

complete output:

==================
WARNING: DATA RACE
Write at 0x00c00000c510 by goroutine 49:
  nhooyr.io/websocket.(*Conn).reader()
      /home/runner/go/pkg/mod/nhooyr.io/websocket@v1.7.2/conn.go:443 +0x2ef
  nhooyr.io/websocket.(*Conn).waitClose()
      /home/runner/go/pkg/mod/nhooyr.io/websocket@v1.7.2/conn.go:962 +0x3fd
  nhooyr.io/websocket.(*Conn).writeClose()
      /home/runner/go/pkg/mod/nhooyr.io/websocket@v1.7.2/conn.go:928 +0x330
  nhooyr.io/websocket.(*Conn).exportedClose()
      /home/runner/go/pkg/mod/nhooyr.io/websocket@v1.7.2/conn.go:888 +0x263
  nhooyr.io/websocket.(*Conn).Close()
      /home/runner/go/pkg/mod/nhooyr.io/websocket@v1.7.2/conn.go:856 +0x7c
  github.com/andersfylling/disgord/internal/gateway.(*nhooyr).Close()
...

Previous read at 0x00c00000c510 by goroutine 78:
  nhooyr.io/websocket.(*messageReader).read()
      /home/runner/go/pkg/mod/nhooyr.io/websocket@v1.7.2/conn.go:482 +0xc4e
  nhooyr.io/websocket.(*messageReader).Read()
      /home/runner/go/pkg/mod/nhooyr.io/websocket@v1.7.2/conn.go:468 +0x66
  bytes.(*Buffer).ReadFrom()
      /opt/hostedtoolcache/go/1.13.4/x64/src/bytes/buffer.go:204 +0x158
  io/ioutil.readAll()
      /opt/hostedtoolcache/go/1.13.4/x64/src/io/ioutil/ioutil.go:36 +0x13e
  nhooyr.io/websocket.(*Conn).Read()
      /opt/hostedtoolcache/go/1.13.4/x64/src/io/ioutil/ioutil.go:45 +0x101
  github.com/andersfylling/disgord/internal/gateway.(*nhooyr).Read()
...

I'm unable to copy the complete output, but it should be found in the link given. The reason you see multiple of these is as I have 4 websockets I'm trying to close.

See previous issue, that I thought I had fixed (single websocket connection): andersfylling/disgord#236

Some of the error messages returned from the Read method of your lib was:

  • cannot use EOFed reader
  • failed to read frame payload: unexpected EOF

Is this happening because I try to execute a Read after a close? I understand it as your lib dispatches a close such that the Read method will not block. I just can't figure out, right now why I would be reading twice.

	internal, cancel := context.WithCancel(context.Background())
	for {
		// check if application has closed
		select {
		case <-ctx.Done():
			c.log.Debug(c.getLogPrefix(), "closing receiver")
			return
		case <-internal.Done():
			go c.reconnect()
			c.log.Debug(c.getLogPrefix(), "closing receiver after read error")
			return
		default:
		}

		var packet []byte
		var err error
		if packet, err = c.conn.Read(context.Background()); err != nil {
			cancel()
			continue
		}

My disconnect method might call Close twice.

I'm a bit baffled; I've been trying to fix this for a while and as this hasn't been an issue before, so I'm sure I've done something weird. I'm asking here, hoping, that you might have an idea what to look for(?) as I'm struggling to reproduce this issue consistently.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions