-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
clarify shutdown procedure #3962
Comments
Hi @fholzer! Sorry for the late response here, and thank you for your detailed issue!
Calling the context on
This is an important data point, and a very strong argument for changing the behavior of I suggest changing the API such that:
Open questions:
@fholzer, wdyt? Does this API make more sense to you? |
We could count the number of connections tracked by the |
I tried to figure this out, looking at winsock API, and man pages for linux tcp functions. After going down that rabbit hole I ended up finding something in the linux kernel source, and something in the TCP RFC 9293. i am not entirely sure how to interpret the paragraph about the "LISTEN STATE" in the "Close Call" section. It doesn't talk about implementation details like the accept queue. The exact behavior could very well be implementation(/OS) specific. Based on what I found in the Linux source code, i think that the kernel sends RST to any established connection that is not yet returned to user space via an accept call. With that in mind, if you want to model the behavior after Linux TCP stack, then any connection that hasn't been returned yet to the user via an accept call should be closed. Regardless of whether the handshake is in progress or completed already. Ideally not silently, but in a way that let's the remote end know that something failed, though I don't know enough about the QUIC spec to say how that could/should be done. Sorry, haven't had time to look into the convenience function |
Thanks for researching, @fholzer!
It's reasonable to assume that most users will call This means that we'll only need to deal with connections that are still handshaking. Unfortunately, there's no dedicated error code defined for that in the RFC. CONNECTION_REFUSED seems like the best fit though. |
If I understand correctly, that means calling close on the listener, while having another go routine call Reg. close during handshake, CONNECTION_REFUSED looks like a good choice. |
#4072 implements this logic when using a |
I'm not sure about this anymore. The problem is that if you use |
While writing up a summary for #3961 I realized that quic-go's
Listener.Close()
behaves differently than Go'sTCPListener.Close()
with the former closing all active connection, and the latter not doing that.Conceptually I like the idea of being able to first stop listening for new connections, then take care of gracefully shutting down any active connections. Another issue is that
listener.Close()
doesn't accept a user error likeconnection.CloseWithError(error)
does. Even if it would accept an error, users may not want to close all active connections with the same error.I also noticed that I can cancel calls to
listener.Accept(ctx)
by cancelling the passed context, though I am not sure if it would have an adverse effect when not calling Accept for some time and clients want to open new connections.As it is now I have to decide between:
listener.Close()
and not being able to convey the desired error to the remote side (neither to have it surfaced via connections context cancellation cause, see connection: surface connection error as connection context cancellation cause #3961)listener.Close()
, also callingconn.CloseWithError(err)
, and hope thatconn.CloseWithError(err)
can cleanly close the connection beforelistener.Close()
does what it does.listener.Accept(ctx)
calls, closing all open connections viaconn.CloseWithError(err)
, once all connection contexts are done, close the listener, then the transport, then the transport.Conn.I have a feeling that option 3 is probably the recommended way, but unsure about cancelling the context on
listener.Accept(ctx)
. Though upon further testing I found that even when cancelling the accept context, the library still continues to accept connections. At least on client side the call totransport.Dial
completes witherr = nil
. Later, aftertransport.Close
is called on the server, the client receivesApplication error 0x0 (remote)
.The text was updated successfully, but these errors were encountered: