You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// If the request sending was offloaded to be done concurrently and not awaited within SendAsync (by calling connection.LogException),
136
+
// the _sendBuffer disposal is the responsibility of that offloaded task to prevent returning the buffer to the pool while it still might be in use.
137
+
if(!_finishingBackgroundWrite)
138
+
{
139
+
_sendBuffer.Dispose();
140
+
}
141
+
// If the response receiving was offloaded to be done concurrently and not awaited within SendAsync (by calling connection.LogException),
142
+
// the _recvBuffer disposal is the responsibility of that offloaded task to prevent returning the buffer to the pool while it still might be in use.
143
+
if(!_finishingBackgroundRead)
144
+
{
145
+
_recvBuffer.Dispose();
146
+
}
135
147
}
136
148
137
149
publicvoidGoAway()
@@ -196,6 +208,11 @@ await Task.WhenAny(sendRequestTask, readResponseTask).ConfigureAwait(false) == s
196
208
}
197
209
catch
198
210
{
211
+
// This is a best effort attempt to transfer the responsibility of disposing _recvBuffer to ReadResponseAsync.
212
+
// The task might be past checking the variable or already finished, in which case the buffer won't be returned to the pool.
213
+
// Not returning the buffer to the pool is an acceptable trade-off for making sure that the buffer is not used after it's been returned.
214
+
_finishingBackgroundRead=true;
215
+
199
216
// Exceptions will be bubbled up from sendRequestTask here,
200
217
// which means the result of readResponseTask won't be observed directly:
201
218
// Do a background await to log any exceptions.
@@ -205,6 +222,11 @@ await Task.WhenAny(sendRequestTask, readResponseTask).ConfigureAwait(false) == s
205
222
}
206
223
else
207
224
{
225
+
// This is a best effort attempt to transfer the responsibility of disposing _sendBuffer to SendContentAsync.
226
+
// The task might be past checking the variable or already finished, in which case the buffer won't be returned to the pool.
227
+
// Not returning the buffer to the pool is an acceptable trade-off for making sure that the buffer is not used after it's been returned.
228
+
_finishingBackgroundWrite=true;
229
+
208
230
// Duplex is being used, so we can't wait for content to finish sending.
209
231
// Do a background await to log any exceptions.
210
232
_connection.LogExceptions(sendRequestTask);
@@ -226,12 +248,6 @@ await Task.WhenAny(sendRequestTask, readResponseTask).ConfigureAwait(false) == s
226
248
{
227
249
// The server doesn't need the whole request to respond so it's aborting its reading side gracefully, see https://datatracker.ietf.org/doc/html/rfc9114#section-4.1-15.
228
250
}
229
-
catch(OperationCanceledException)
230
-
{
231
-
// If the request got cancelled before WritesClosed completed, avoid leaking an unobserved task exception.
0 commit comments