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.

Reply via email to