Hi David, Ah ha, magic. And all fixed. Sometimes another pair of eyes is all that is required. While I had no doubt the race detector was correct in reporting the race the key line in the reply was "The only goroutine that can safely close a channel is the one that is writing to it." After that everything made sense and I could then see the other go routing calling the close().
Anyhow updated, correct, and now simpler code is here: https://play.golang.org/p/eUYLxQqcEr Thanks Owen On Mon, 2017-04-24 at 13:10 -0700, dwah...@gmail.com wrote: > Hi Owen, > > > > > > > > > > > > > > > > > > > My understanding is that when a key is > > > > > > > > > > > > > > > > > > pressed that will terminate the program. This closes the quit channel, which causes the deferred closeChans() to be called. That in turn closes the done and the bus channels in that order. Closing the done channel causes the select in simBus() to complete in the <-done case. This causes the bus channel to drain. The next call to writeToBus, which is triggered by the timer going off - should then fail. The cancelled() function should return true at this point so no attempt should be made to write to the bus channel. > > > > > > As I understand the data race below, this logic is flawed. Attempts are being made to write to the bus channel after it has been closed. > > > > > > > > > > > > The race detector is correct. When you write "the next call to write to us", you're making a faulty assumption -- namely, the assumption that each call to writeToBus happens either before closeChans, or after closeChans. But the two functions are called by separate goroutines and can execute concurrently. So one can write to the bus while the other is trying to close it, which is a race condition. > > > > > > > (Similarly, when you write things like "Closing the done causes the select in simBus() to complete, you should always remember that each read from a channel happens *after* the corresponding write, asynchronously, at a time which is not guaranteed.) > > > > > This is a fundamental flaw with your approach. The only goroutine that can safely close a channel is the one that is writing to it. So your dataPump function needs to be the one to listen for the "quit" signal. > > Hope this helps! > -- David > > > > > > -- > > > You received this message because you are subscribed to the Google Groups "golang-nuts" group. > > > > To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. > > > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.