New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
net: unclear how to confirm synchronously that a net.TCPListener is closed #21833
Comments
Creates a happens before relationship, a value can only be received from HasStopped if the sender, above has reached that step. We don't the issue tracker to ask questions, so I'm going to close this. Please see https://golang.org/wiki/Questions for good places to ask. Thanks. |
I'm sorry if the question was either misdirected or poorly phrased. I should clarify that I think this may indicate either a bug in the documentation or in the runtime. Specifically, TCPListener.Close is documented as "Close stops listening on the TCP address." The test case demonstrates that a single call to |
Don't close and reopen listeners: golang/go#21833
Don't close and reopen listeners: golang/go#21833
Don't close and reopen listeners: golang/go#21833
Don't close and reopen listeners: golang/go#21833
Don't close and reopen listeners: golang/go#21833
What version of Go are you using (
go version
)?1.9
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env
)?What did you do?
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:
Listener.Close()
to interrupt theListener.Accept()
call on the other goroutineListener.Close()
itself and exitListener.Close()
Observed behavior:
-race
)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 theclose(2)
call on the underlying socket has not executed by the time the goroutine executingmain()
tries to create the new listener; therefore thebind(2)
call fails withEADDRINUSE
. Based on my reading of the runtime's source code, this is because the underlying file descriptor is reference-counted, andclose(2)
is not called until the reference count drops to 0. (Since the runtime setsSO_REUSEADDR
on the socket, the address can be rebound immediately afterclose(2)
.)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 themain()
goroutine callsListener.Close()
). Is there any way to get a synchronous guarantee that the underlying socket has been closed?Thanks very much for your time.
The text was updated successfully, but these errors were encountered: