On Wed, Jul 12, 2017 at 8:56 AM, James Abley <james.ab...@gmail.com> wrote: > > Labels for clarity: > > 1. goroutine 1 spawns goroutine 2 to read from Oregon, and spawns goroutine > 3 to read from Virginia. > 2. goroutine 1 calls waitForSearchCompletion and enters the select. Nothing > can proceed, so that select blocks. > 3. goroutine 3 completes Search and enters its select, sees that the context > isn't done, and sends on the respc channel > 4. goroutine 1 can now proceed, by reading from the respc channel > 5. goroutine 2 completes the Search and enters its select > 6. ??? > > At this point, it seems as though goroutine 2 blocks if it uses a case, and > proceeds if it uses default. > > If it blocks (is it blocked by goroutine 1?), then goroutine 1 exits from > waitForSearchCompletion, and exits from Search, the deferred cancel() is > evaluated, and the context is marked as done. The select in goroutine 2 sees > the context as Done and does not write to the channel. > > (I have never seen this version fail, having run soak tests that have > exercised it for billions of iterations in a test application. It may be a > correct programme, or I may have been lucky so far). > > If it proceeds, then goroutine 2 is able to write to the channel (which is > never subsequently read, and thus leaks, and eventually starts failing > hard). > > From https://golang.org/ref/spec#Send_statements > >> A send on an unbuffered channel can proceed if a receiver is ready > > When is the receiver respc ready for another write (by goroutine 2)? Is the > receiver ready after `case r := <-respc:` has been evaluated in > waitForSearchCompletion? Does it need to wait until the StatementList of the > CommClause starts being run? Is it after that select exits? > > The thing that's confusing me is that the code in waitForSeachCompletion > hasn't changed. I do not understand how I've changed the "readiness" of the > receiver. Presumably the choice of case or default is causing that?
A send on an unbuffered channel is only ready when some other goroutine reads from the channel. The sender will block until that happens. In your program, when goroutine 1 gets an answer and writes to the channel, waitForSearchCompletion reads the value and returns. At that point nothing ever reads from respc. So when goroutine 2 tries to write to respc, it blocks waiting for a reader that never appears. Ian -- 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.