On Mon, Jul 8, 2019 at 9:14 PM Daniel Eloff <dan.el...@gmail.com> wrote:
>
> If a select statement has multiple channels ready when it runs, then it will 
> choose one at a random. So if you fire something across a channel that holds 
> a resource, like an open file descriptor - you have no guarantees that the 
> other end of the channel receives it. The (possibly full) channel will get 
> garbage collected later and the resource will leak in that case.
>
> Some code that explains things better than my clumsy prose:
>
> Receiver:
>  // Wait on the channel, or for timeout
>  select {
>  case fd := <-channel:
>      return fd, nil
>  case <-time.After(queue.timeout):
>      return nil, ErrTimeoutElapsed
>  }
>
> Sender:
>  channel <- fd
>
> What happens when the timeout races with the channel send? I think it's 
> possible the select handles the timeout in that case and leaves the channel 
> containing a connection alone.
>
> Am I right that this is a problem? How might I fix this code?

There are many approaches.  Here is a simple one:

    select {
    case fd := <-channel:
        return fd, nil
    case <-time.After(queue.timeout):
        go func() {
            <-channel.Close()
        }()
        return nil, ErrTimeoutElapsed
    }

Another approach is to use a context.Context on the sending side, and
cancel the Context if the timeout occurs.  I won't write that out, but
see https://blog.golang.org/context .

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.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAOyqgcU3-KKjg-sHYQZoQEJbkgz96fSWbUr7SGZihbgRkKcv6Q%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to