I'm not singling out Dave Cheney here, I'd just like to check my 
understanding of Go's resource handling and concurrency.

In this blog post a "prototypical network server" is presented:

   https://dave.cheney.net/2017/08/20/context-isnt-for-cancellation

Code:

func serve(l net.Listener) error {
        var wg sync.WaitGroup
        var conn net.Conn
        var err error
        for {
                conn, err = l.Accept()
                if err != nil {
                        break
                }
                wg.Add(1)
                go func(c net.Conn) {
                        defer wg.Done()
                        handle(c)
                }(conn)
        }
        wg.Wait()
        return err
}

My understanding is that this contains a race condition. Specifically, a 
goroutine switch can occur at the entry to wg.Add(1), switching to 
wg.Wait() in the main goroutine. At this point, a connection has been 
accepted, but the WaitGroup counter has not been incremented, so the serve 
function will terminate while silently dropping a network connection (the 
connection will be accepted, but never handled, so will probably eventually 
time out on the client side and leak a file descriptor on the server side).

Is this understanding correct? Furthermore, I suspect that it's impossible 
to implement race-free graceful termination using only sync.WaitGroups. Is 
it actually possible to do so?

Thanks for any correction, and apologies to Dave for picking on his code.

Cheers,
Tom

-- 
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