Skip to content
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

doc: document that unsynchronized (channel send + channel close) is a data race #27769

Closed
deckarep opened this issue Sep 20, 2018 · 12 comments
Closed
Labels
Documentation FrozenDueToAge help wanted Suggested Issues that may be good for new contributors looking for work to do.
Milestone

Comments

@deckarep
Copy link

deckarep commented Sep 20, 2018

Now that I'm aware of this behavior i'm only proposing that this be documented in Go's documentation. My rationale is that since channels are built to be threadsafe, I would have assumed all operations against them are threadsafe. ie, sending, receiving, closing.

What version of Go are you using (go version)? go version go1.11 darwin/amd64

Does this issue reproduce with the latest release? Yes

What operating system and processor architecture are you using (go env)?

GOHOSTARCH="amd64"
GOHOSTOS="darwin"

What did you do?

First off, my code was flawed but it exposed a data-race that I thought would not be possible. My assumption was that all operations on channels are thread-safe by design..at the worst I would have expected the code to panic.

  • Sending on a channel (threadsafe) Well-understood
  • Receiving on a channel (threadsafe) Well-understood
  • Sending on a channel already closed (panics) Well-understood
  • Closing a channel (not threadsafe) Huh?

https://stackoverflow.com/questions/47714470/go-race-condition-when-closing-a-go-channel

What did you expect to see?

I expected a panic to occur but instead this data-race shows up.

What did you see instead?

WARNING: DATA RACE
Read at 0x00c0000b4000 by goroutine 10:
  runtime.chansend()
      /usr/local/Cellar/go/1.11/libexec/src/runtime/chan.go:140 +0x0
  main.tx()
      /Users/deckarep/Desktop/channel_close_race/main.go:15 +0x66

Previous write at 0x00c0000b4000 by main goroutine:
  runtime.closechan()
      /usr/local/Cellar/go/1.11/libexec/src/runtime/chan.go:327 +0x0
  main.main()
      /Users/deckarep/Desktop/channel_close_race/main.go:38 +0x11f
@randall77
Copy link
Contributor

It's reported as a data race, but in reality it's a "your send and close are unordered" error. What it means is that although in this execution the send came before the close, there's no observable ordering enforcing that - the next time you run, it only takes different choices by the scheduler to make the send come after the close and cause a panic.

@deckarep
Copy link
Author

@randall77 - thanks for the explanation. I think that is an understandable reasoning on why the race detector trips. I'm just questioning if this behavior should be documented...if so where would such docs belong?

@randall77
Copy link
Contributor

@deckarep: I don't really know where such documentation should live. We have docs about how to use the race detector, but I don't see any place to describe the kind of races it finds.

@agnivade
Copy link
Contributor

@dvyukov

@dvyukov
Copy link
Member

dvyukov commented Sep 21, 2018

What @randall77 said.
It's not a /data race/ per se, but it's a bug worth detecting. It's both hard to discriminate this in race detector, and more of a one-off corner case, so race detector just reports this as it reports all other data races.

Re documenting, I don't think there is a single doc that all users of race detector has read before using it. Thus I don't think this can be solved with documentation. But we could mention this in https://golang.org/doc/articles/race_detector.html#Typical_Data_Races

@agnivade agnivade added Suggested Issues that may be good for new contributors looking for work to do. help wanted labels Sep 21, 2018
@agnivade agnivade added this to the Unplanned milestone Sep 21, 2018
@deckarep
Copy link
Author

I’m happy to take a crack and write something up to start off the docs. Then I can consult the Go team to help with wording and accuracy.

@Loveuse
Copy link

Loveuse commented Sep 29, 2018

I think https://golang.org/ref/mem under the Channel communication section might also be a good place to mention it since the send on the channel may happen before its closure.

@as
Copy link
Contributor

as commented Feb 24, 2019

It would be nice if the documentation also mentioned that this race is a symptom of ineffective producer/consumer designation, not just ordering quirks in the program.

@andybons andybons changed the title Document that unsynchronized (channel send + channel close) is a data race. doc: document that unsynchronized (channel send + channel close) is a data race May 14, 2019
@andybons
Copy link
Member

@deckarep are you still interested in doing this?

@tpaschalis
Copy link
Contributor

Hope it's okay to bring this up nearly a year after.

I'm looking to contribute for the first time, and documentation seems a safe and easy place to start. The following code still produces a data race.

func TestRace(t *testing.T) {
    var c = make(chan byte, 20)
    go func() {
        defer func() {
            if r := recover(); r == nil {
                t.Error("expected panic error")
            }
        }()
        for i := 0; i < 25; i++ {
            c <- byte(0)
        }
        t.Error("expected a panic")
    }()
    close(c)
}

I could draft a paragraph to document this on https://golang.org/doc/articles/race_detector.html#Typical_Data_Races and get some feedback. Does it sound okay to you?

@gopherbot
Copy link

Change https://golang.org/cl/196681 mentions this issue: doc : document a race condition caused by unordered send and close

@gopherbot
Copy link

Change https://golang.org/cl/219637 mentions this issue: doc: race condition in unsynchronized send/close

chlunde added a commit to chlunde/jaeger that referenced this issue Oct 22, 2020
TBufferedServer.Close() may close the data channel before
Serve detects it. Move chan close() to Serve to prevent
a panic caused by sending on a closed channel.

See also golang/go#27769 (comment)

	=== RUN   TestTBufferedServer_SendReceive
	==================
	WARNING: DATA RACE
	Write at 0x00c000074850 by goroutine 9:
	  runtime.closechan()
	      /home/travis/.gimme/versions/go1.15.2.linux.amd64/src/runtime/chan.go:352 +0x0
	  github.com/jaegertracing/jaeger/cmd/agent/app/servers.(*TBufferedServer).Stop()
	...
	Previous read at 0x00c000074850 by goroutine 10:
	  runtime.chansend()
	      /home/travis/.gimme/versions/go1.15.2.linux.amd64/src/runtime/chan.go:158 +0x0
	  github.com/jaegertracing/jaeger/cmd/agent/app/servers.(*TBufferedServer).Serve()
	      /home/travis/gopath/src/github.com/jaegertracing/jaeger/cmd/agent/app/servers/tbuffered_server.go:97 +0x264
	...
	==================
	    testing.go:1042: race detected during execution of test
	--- FAIL: TestTBufferedServer_SendReceive (0.01s)

Closes jaegertracing#2577

Signed-off-by: Carl Henrik Lunde <chlunde@ifi.uio.no>
yurishkuro pushed a commit to jaegertracing/jaeger that referenced this issue Oct 25, 2020
TBufferedServer.Close() may close the data channel before
Serve detects it. Move chan close() to Serve to prevent
a panic caused by sending on a closed channel.

See also golang/go#27769 (comment)

	=== RUN   TestTBufferedServer_SendReceive
	==================
	WARNING: DATA RACE
	Write at 0x00c000074850 by goroutine 9:
	  runtime.closechan()
	      /home/travis/.gimme/versions/go1.15.2.linux.amd64/src/runtime/chan.go:352 +0x0
	  github.com/jaegertracing/jaeger/cmd/agent/app/servers.(*TBufferedServer).Stop()
	...
	Previous read at 0x00c000074850 by goroutine 10:
	  runtime.chansend()
	      /home/travis/.gimme/versions/go1.15.2.linux.amd64/src/runtime/chan.go:158 +0x0
	  github.com/jaegertracing/jaeger/cmd/agent/app/servers.(*TBufferedServer).Serve()
	      /home/travis/gopath/src/github.com/jaegertracing/jaeger/cmd/agent/app/servers/tbuffered_server.go:97 +0x264
	...
	==================
	    testing.go:1042: race detected during execution of test
	--- FAIL: TestTBufferedServer_SendReceive (0.01s)

Closes #2577

Signed-off-by: Carl Henrik Lunde <chlunde@ifi.uio.no>
@golang golang locked and limited conversation to collaborators Mar 2, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Documentation FrozenDueToAge help wanted Suggested Issues that may be good for new contributors looking for work to do.
Projects
None yet
Development

No branches or pull requests

9 participants