Hi Owen,
On Monday, April 24, 2017 at 1:23:58 PM UTC-5, Owen Waller wrote: > > 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.