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.