From 4685fb2555a9b21eda84a2f7e4fd4c85bef341f0 Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Thu, 23 May 2024 09:37:57 +0200 Subject: [PATCH 1/3] Initial commit to prototype --- .../Net/Http/SocketsHttpHandler/Http3Connection.cs | 11 +++++++++++ .../Net/Http/SocketsHttpHandler/Http3RequestStream.cs | 6 ++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs index 75b9d9b1f8a964..954e5b2d209ea1 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs @@ -28,6 +28,8 @@ internal sealed class Http3Connection : HttpConnectionBase // Keep a collection of requests around so we can process GOAWAY. private readonly Dictionary _activeRequests = new Dictionary(); + internal readonly List _streamDisposals = []; + // Set when GOAWAY is being processed, when aborting, or when disposing. private long _firstRejectedStreamId = -1; @@ -105,6 +107,7 @@ public override void Dispose() if (_firstRejectedStreamId == -1) { _firstRejectedStreamId = long.MaxValue; + Task.WhenAll(_streamDisposals).GetAwaiter().GetResult(); CheckForShutdown(); } } @@ -363,6 +366,14 @@ public void RemoveStream(QuicStream stream) } } + public void QueueStreamForDisposal(QuicStream stream) + { + lock (SyncObj) + { + _streamDisposals.Add(stream.DisposeAsync().AsTask()); + } + } + public override long GetIdleTicks(long nowTicks) => throw new NotImplementedException("We aren't scavenging HTTP3 connections yet"); public override void Trace(string message, [CallerMemberName] string? memberName = null) => diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs index ef2532b2b22d08..dbee3ca5d1e759 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs @@ -101,15 +101,17 @@ private void RemoveFromConnectionIfDone() } } - public async ValueTask DisposeAsync() + public ValueTask DisposeAsync() { if (!_disposed) { _disposed = true; AbortStream(); - await _stream.DisposeAsync().ConfigureAwait(false); + _connection.QueueStreamForDisposal(_stream); DisposeSyncHelper(); } + + return ValueTask.CompletedTask; } private void DisposeSyncHelper() From 84cf2b93948d63e661730881e4aa76331e5616d2 Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Mon, 3 Jun 2024 13:22:34 +0200 Subject: [PATCH 2/3] Move QueueStreamForDisposal To Dispose --- .../Net/Http/SocketsHttpHandler/Http3RequestStream.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs index dbee3ca5d1e759..67d2487b9c0edd 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3RequestStream.cs @@ -88,7 +88,7 @@ public void Dispose() { _disposed = true; AbortStream(); - _stream.Dispose(); + _connection.QueueStreamForDisposal(_stream); DisposeSyncHelper(); } } @@ -101,17 +101,15 @@ private void RemoveFromConnectionIfDone() } } - public ValueTask DisposeAsync() + public async ValueTask DisposeAsync() { if (!_disposed) { _disposed = true; AbortStream(); - _connection.QueueStreamForDisposal(_stream); + await _stream.DisposeAsync().ConfigureAwait(false); DisposeSyncHelper(); } - - return ValueTask.CompletedTask; } private void DisposeSyncHelper() From 7ffcf17f2197ae1ec86bbe0d3f6b9116e0cf7dd7 Mon Sep 17 00:00:00 2001 From: Ahmet Ibrahim Aksoy Date: Mon, 3 Jun 2024 13:39:02 +0200 Subject: [PATCH 3/3] Move awaiting for stream disposals to CheckForShutdown in H3Conn --- .../System/Net/Http/SocketsHttpHandler/Http3Connection.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs index 954e5b2d209ea1..b76c0b79ec0665 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http3Connection.cs @@ -107,7 +107,6 @@ public override void Dispose() if (_firstRejectedStreamId == -1) { _firstRejectedStreamId = long.MaxValue; - Task.WhenAll(_streamDisposals).GetAwaiter().GetResult(); CheckForShutdown(); } } @@ -129,6 +128,10 @@ private void CheckForShutdown() if (_connection != null) { + // Make sure we've disposed every stream before closing the connection. + + Task.WhenAll(_streamDisposals).GetAwaiter().GetResult(); + // Close the QuicConnection in the background. _connectionClosedTask ??= _connection.CloseAsync((long)Http3ErrorCode.NoError).AsTask();