I'm having trouble understanding an aspect of the `Listener` API. Specifically, when using `net.Listen` to bind to an address, how can one close the listener in such a way that the address is guaranteed to be available for binding again?
Here's a test case for Go 1.9: https://gist.github.com/slingamn/f1f2ef4a8d004e67a9b0f27b698a5b13 This is a simple TCP ping-pong server that uses channels for connection handoff. The wrinkle is that I'm trying to periodically close the connection from a separate goroutine, then open a new connection that rebinds to the address. (The non-toy use case for this is implementing reload of configuration files in a long-running server.) This is implemented by: 1. Using `Listener.Close()` to interrupt the `Listener.Accept()` call on the other goroutine 2. Using a channel to tell the other goroutine that it should call `Listener.Close()` itself and exit 3. Using a channel to wait for the other goroutine to complete its call to `Listener.Close()` Observed behavior: 1. As written, the code appears to work (it runs correctly, and no races are reported under stress testing with `-race`) 2. When step 3 above (waiting for the other goroutine to call `Listener.Close`) is omitted (by running the test case with the command-line argument `--waitforstop=false`), the program crashes with: `listen error: listen tcp :7777: bind: address already in use`. According to `strace`, the problem is that the `close(2)` call on the underlying socket has not executed by the time the goroutine executing `main()` tries to create the new listener; therefore the `bind(2)` call fails with `EADDRINUSE`. Based on my reading of the runtime's source code, this is because the underlying file descriptor is reference-counted, and `close(2)` is not called until the reference count drops to 0. The first `Close()` call merely results in a decref, and the second call closes the file descriptor. The problem I'm having is that based on my reading of the documentation, I'm unable to either prove that step 3 makes the code safe (i.e., that by the time `<-wrapper.HasStopped` finishes, the underlying socket has definitely been closed), or understand why the omission of step 3 makes the code unsafe (i.e., why the reference count does not immediately go to 0 after the `main()` goroutine calls `Listener.Close()`). Is there any way to get a synchronous guarantee that the underlying socket has been closed? Thanks very much for your time. -- 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.