-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
Fix idle HTTP/2 connection KeepAliveTimeout teardown #96157
Conversation
Tagging subscribers to this area: @dotnet/ncl Issue DetailsFixes #95621 for 9.0. #95621 reports that the following exception was thrown in a timer callback, which in turn crashed the process:
It is clear that Looking at the code involved in shutting down an HTTP/2 connection and removing unrelated things, it looks like this bool _shutdown;
Abort()
{
lock (SyncObject)
Shutdown();
}
Dispose()
{
lock (SyncObject)
Shutdown();
}
Shutdown()
{
if (!_shutdown)
{
InvalidateHttp2Connection(this);
_shutdown = true;
if (_streamsInUse == 0)
FinalTeardown();
}
}
InvalidateHttp2Connection(connection)
{
if (TryRemoveConnectionFromPool())
connection.Dispose();
}
// This should be called exactly once
void FinalTeardown() => _writeChannel.Writer.Complete();
This effectively means that if an idle HTTP/2 connection hits the The The product change in this PR moves the toggling of 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.
LGTM
/azp run runtime-libraries-coreclr outerloop |
Azure Pipelines successfully started running 1 pipeline(s). |
/backport to release/8.0-staging |
Started backporting to release/8.0-staging: https://github.com/dotnet/runtime/actions/runs/7256023935 |
...libraries/System.Net.Http/tests/FunctionalTests/SocketsHttpHandlerTest.Http2KeepAlivePing.cs
Outdated
Show resolved
Hide resolved
…pHandlerTest.Http2KeepAlivePing.cs
Fixes #95621 for 9.0.
This was a regression introduced in 8.0 by #90094.
#95621 reports that the following exception was thrown in a timer callback, which in turn crashed the process:
It is clear that
FinalTeardown
was somehow called twice.Looking at the code involved in shutting down an HTTP/2 connection and removing unrelated things, it looks like this
Shutdown
callsInvalidateHttp2Connection
, which may call back intoDispose
, which calls intoShutdown
.Because we set
_shutdown
after callingInvalidateHttp2Connection
, we entered theif (!_shutdown)
block twice (on the same call stack).If the
_streamsInUse == 0
condition holds, we will call intoFinalTeardown
twice.This effectively means that if an idle HTTP/2 connection hits the
KeepAliveTimeout
, we'll crash the process.The
HttpKeepAlivePingPolicy_Always_NoPingResponseBetweenStreams_SecondRequestShouldFail
test was meant to test this condition, but sadly it was always sending the second request on the client, so we weren't exercising the_streamsInUse == 0
condition.After fixing the test, it is a 100 % repro for the reported issue.
The product change in this PR moves the toggling of the
_shutdown
flag before the call toInvalidateHttp2Connection
.