Skip to content

Commit 67023fa

Browse files
committed
Only dispose the stream pipe wrapper and more tests
1 parent 1a7b2c2 commit 67023fa

File tree

2 files changed

+76
-12
lines changed

2 files changed

+76
-12
lines changed

src/Servers/Kestrel/Core/src/Internal/Http/HttpProtocol.FeatureCollection.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,7 @@ PipeWriter IResponseBodyPipeFeature.ResponseBodyPipe
205205
{
206206
var responseBody = new WriteOnlyPipeStream(ResponsePipeWriter);
207207
ResponseBody = responseBody;
208-
209-
RegisterWrapperForDisposal(responseBody);
208+
_cachedResponsePipeWriter = ResponsePipeWriter;
210209
}
211210
}
212211
}
@@ -225,18 +224,15 @@ Stream IHttpResponseFeature.Body
225224
var responsePipeWriter = new StreamPipeWriter(ResponseBody, minimumSegmentSize: 4096, _context.MemoryPool);
226225
ResponsePipeWriter = responsePipeWriter;
227226
_cachedResponseBodyStream = ResponseBody;
228-
RegisterWrapperForDisposal(responsePipeWriter);
229-
}
230-
}
231-
}
232227

233-
private void RegisterWrapperForDisposal(IDisposable responseBody)
234-
{
235-
if (_wrapperObjectsToDispose == null)
236-
{
237-
_wrapperObjectsToDispose = new List<IDisposable>();
228+
// The StreamPipeWrapper needs to be disposed as it hold onto blocks of memory
229+
if (_wrapperObjectsToDispose == null)
230+
{
231+
_wrapperObjectsToDispose = new List<IDisposable>();
232+
}
233+
_wrapperObjectsToDispose.Add(responsePipeWriter);
234+
}
238235
}
239-
_wrapperObjectsToDispose.Add(responseBody);
240236
}
241237

242238
protected void ResetHttp1Features()

src/Servers/Kestrel/test/InMemory.FunctionalTests/ResponseTests.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3517,6 +3517,74 @@ await connection.Receive(
35173517
}
35183518
}
35193519

3520+
[Fact]
3521+
public async Task ResponseSetBodyToSameValueTwiceGetPipeMultipleTimesSameObject()
3522+
{
3523+
using (var server = new TestServer(async httpContext =>
3524+
{
3525+
var memoryStream = new MemoryStream();
3526+
httpContext.Response.Body = memoryStream;
3527+
var bodyPipe1 = httpContext.Response.BodyPipe;
3528+
3529+
httpContext.Response.Body = memoryStream;
3530+
var bodyPipe2 = httpContext.Response.BodyPipe;
3531+
3532+
Assert.Equal(bodyPipe1, bodyPipe2);
3533+
await Task.CompletedTask;
3534+
}, new TestServiceContext(LoggerFactory)))
3535+
{
3536+
using (var connection = server.CreateConnection())
3537+
{
3538+
await connection.Send(
3539+
"GET / HTTP/1.1",
3540+
"Host:",
3541+
"",
3542+
"");
3543+
await connection.Receive(
3544+
"HTTP/1.1 200 OK",
3545+
$"Date: {server.Context.DateHeaderValue}",
3546+
"Content-Length: 0",
3547+
"",
3548+
"");
3549+
}
3550+
await server.StopAsync();
3551+
}
3552+
}
3553+
3554+
[Fact]
3555+
public async Task ResponseSetPipeToSameValueTwiceGetBodyMultipleTimesSameObject()
3556+
{
3557+
using (var server = new TestServer(async httpContext =>
3558+
{
3559+
var pipeWriter = new Pipe().Writer;
3560+
httpContext.Response.BodyPipe = pipeWriter;
3561+
var body1 = httpContext.Response.Body;
3562+
3563+
httpContext.Response.BodyPipe = pipeWriter;
3564+
var body2 = httpContext.Response.Body;
3565+
3566+
Assert.Equal(body1, body2);
3567+
await Task.CompletedTask;
3568+
}, new TestServiceContext(LoggerFactory)))
3569+
{
3570+
using (var connection = server.CreateConnection())
3571+
{
3572+
await connection.Send(
3573+
"GET / HTTP/1.1",
3574+
"Host:",
3575+
"",
3576+
"");
3577+
await connection.Receive(
3578+
"HTTP/1.1 200 OK",
3579+
$"Date: {server.Context.DateHeaderValue}",
3580+
"Content-Length: 0",
3581+
"",
3582+
"");
3583+
}
3584+
await server.StopAsync();
3585+
}
3586+
}
3587+
35203588
[Fact]
35213589
public async Task ResponseSetPipeAndBodyPipeIsWrapped()
35223590
{

0 commit comments

Comments
 (0)