-
Notifications
You must be signed in to change notification settings - Fork 581
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
Add a dedicated method for disconnecting TLS connections #10005
Conversation
By now, I'm pretty sure the answer is yes. Evidence: Take two connected Icinga 2 nodes and break individual connections by dropping the packets specific to that connection in a firewall. Both nodes will detect that no messages were received and reconnect, however, the old connection remains in an established state:
That implies that there's probably a resource leak in that scenario (until the kernel decides that the connection is actually dead and returns an error for the socket operations). Unverified theory of what might happen: icinga2/lib/remote/jsonrpcconnection.cpp Line 226 in 9a8620d
Which waits for icinga2/lib/remote/jsonrpcconnection.cpp Lines 112 to 120 in 9a8620d
|
Thing to consider
|
e90acc5
to
3a72a6f
Compare
I resolved conflicts and started implementing |
3a72a6f
to
9d67c26
Compare
While continuing that work, I figured that this might become a bigger rework of This PR on it's own should already be enough of an improvement on its own, after all it even fixes a problem in the HTTP connection handling.
In that regard, I figured that adding comments to these calls why they are fine is good enough, especially when compared that was needed just to add a redundant timeout and spawn a pointless coroutine (e90acc5). I'm leaving the PR in a draft state for the moment because I still want to answer a few detail questions regarding the two new disconnect methods (I removed a |
9d67c26
to
e5b9ff4
Compare
I still couldn't find a good reason to call
That on the other hand turned out to be necessary: as confirmed using strace, without calling |
e5b9ff4
to
7430618
Compare
7430618
to
a6445c7
Compare
a6445c7
to
1cf8617
Compare
Force push was just a rebase to resolve merge conflicts due to changes in indentation, no other (intended) changes. |
1cf8617
to
e6d387d
Compare
And another rebase to get the GitHub Actions going again (actually, I thought the last rebase would already to that, but at that point, #10251 wasn't merged yet) |
@Al2Klimov Please clarify what your expectations are regarding your outstanding comments (#10005 (review), #10005 (review)). Yes, cleaning up the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is almost perfectly fine.
Calling `AsioTlsStream::async_shutdown()` performs a TLS shutdown which exchanges messages (that's why it takes a `yield_context`) and thus has the potential to block the coroutine. Therefore, it should be protected with a timeout. As `async_shutdown()` doesn't simply take a timeout, this has to be implemented using a timer. So far, these timers are scattered throughout the codebase with some places missing them entirely. This commit adds helper functions to properly shutdown a TLS connection with a single function call.
This new helper functions allows deduplicating the timeout handling for `async_shutdown()`.
This new helper function has proper timeout handling which was missing here.
The reason for introducing AsioTlsStream::GracefulDisconnect() was to handle the TLS shutdown properly with a timeout since it involves a timeout. However, the implementation of this timeout involves spwaning coroutines which are redundant in some cases. This commit adds comments to the remaining calls of async_shutdown() stating why calling it is safe in these places.
e6d387d
to
a506d56
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fine.
shutdownTimeout->Cancel(); | ||
|
||
m_Stream->lowest_layer().shutdown(m_Stream->lowest_layer().shutdown_both, ec); | ||
m_Stream->GracefulDisconnect(m_IoStrand, yc); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- ... during this and makes the shutdown unclean. But it is already unclean, see 🪵Log TLS shutdown error🛑, only if any #10259, so... 🤷♂️
Properly closing a TLS connection involves sending some shutdown messages so that both ends know that the connection wasn't truncated maliciously. Exchanging those messages can stall for a long time if the underlying TCP connection is broken. The HTTP connection handling was missing any kind of timeout for the TLS shutdown so that dead connections could hang around for a long time.
This PR introduces two new methods on
AsioTlsStream
, namelyForceDisconnect()
which just wraps the call for closing the TCP connection andGracefulShutdown()
which performs the TLS shutdown with a timeout similar to it was done inJsonRpcConnection::Disconnect()
before.fixes #9986