Only reuse HTTP/2 streams when response writer was completed s… (#20121)

This commit is contained in:
James Newton-King 2020-03-26 18:34:53 +13:00 committed by GitHub
parent f0e6a8933c
commit 84bd089ae3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 7 additions and 16 deletions

View File

@ -86,7 +86,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
_streamEnded = false;
_suffixSent = false;
_suffixSent = false;
_startedWritingDataFrames = false;
_streamCompleted = false;
_writerComplete = false;
@ -462,17 +461,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
// Stream state will move to RequestProcessingStatus.ResponseCompleted
_responseCompleteTaskSource.SetResult(flushResult);
if (readResult.IsCompleted)
{
// Successfully read all data. Wait here for the stream to be reset.
await new ValueTask(_resetAwaitable, _resetAwaitable.Version);
_resetAwaitable.Reset();
}
else
{
// Stream was aborted.
break;
}
// Wait here for the stream to be reset or disposed.
await new ValueTask(_resetAwaitable, _resetAwaitable.Version);
_resetAwaitable.Reset();
} while (!_disposed);
static void ThrowUnexpectedState()
@ -537,6 +528,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
}
_disposed = true;
// Set awaitable after disposed is true to ensure ProcessDataWrites exits successfully.
_resetAwaitable.SetResult(null);
}
}

View File

@ -156,10 +156,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2
// connection's flow-control window.
_inputFlowControl.Abort();
// We only want to reuse a stream that has completely finished writing.
// This is to prevent the situation where Http2OutputProducer.ProcessDataWrites
// is still running in the background.
CanReuse = !_keepAlive && HasResponseCompleted;
// We only want to reuse a stream that was not aborted and has completely finished writing.
// This ensures Http2OutputProducer.ProcessDataWrites is in the correct state to be reused.
CanReuse = !_connectionAborted && HasResponseCompleted;
}
finally
{