Stop streams on finish
Can't use dispose (or close) as can be disposed too early by user code Resolves #263
This commit is contained in:
parent
8c0a1701cd
commit
f60f6c92ca
|
|
@ -204,8 +204,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
MessageBody = MessageBody.For(HttpVersion, _requestHeaders, this);
|
MessageBody = MessageBody.For(HttpVersion, _requestHeaders, this);
|
||||||
_keepAlive = MessageBody.RequestKeepAlive;
|
_keepAlive = MessageBody.RequestKeepAlive;
|
||||||
RequestBody = new FrameRequestStream(MessageBody);
|
var requestBody = new FrameRequestStream(MessageBody);
|
||||||
ResponseBody = new FrameResponseStream(this);
|
RequestBody = requestBody;
|
||||||
|
var responseBody = new FrameResponseStream(this);
|
||||||
|
ResponseBody = responseBody;
|
||||||
DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
|
DuplexStream = new FrameDuplexStream(RequestBody, ResponseBody);
|
||||||
|
|
||||||
var httpContext = HttpContextFactory.Create(this);
|
var httpContext = HttpContextFactory.Create(this);
|
||||||
|
|
@ -236,6 +238,9 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
// Finish reading the request body in case the app did not.
|
// Finish reading the request body in case the app did not.
|
||||||
await MessageBody.Consume();
|
await MessageBody.Consume();
|
||||||
|
|
||||||
|
requestBody.StopAcceptingReads();
|
||||||
|
responseBody.StopAcceptingWrites();
|
||||||
}
|
}
|
||||||
|
|
||||||
terminated = !_keepAlive;
|
terminated = !_keepAlive;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
public class FrameRequestStream : Stream
|
public class FrameRequestStream : Stream
|
||||||
{
|
{
|
||||||
private readonly MessageBody _body;
|
private readonly MessageBody _body;
|
||||||
|
private bool _stopped;
|
||||||
|
|
||||||
public FrameRequestStream(MessageBody body)
|
public FrameRequestStream(MessageBody body)
|
||||||
{
|
{
|
||||||
|
|
@ -50,12 +51,22 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
public override int Read(byte[] buffer, int offset, int count)
|
public override int Read(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
|
if (_stopped)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException("RequestStream has been disposed");
|
||||||
|
}
|
||||||
|
|
||||||
return ReadAsync(buffer, offset, count).GetAwaiter().GetResult();
|
return ReadAsync(buffer, offset, count).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NET451
|
#if NET451
|
||||||
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
|
||||||
{
|
{
|
||||||
|
if (_stopped)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException("RequestStream has been disposed");
|
||||||
|
}
|
||||||
|
|
||||||
var task = ReadAsync(buffer, offset, count, CancellationToken.None, state);
|
var task = ReadAsync(buffer, offset, count, CancellationToken.None, state);
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
{
|
{
|
||||||
|
|
@ -71,6 +82,11 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
private Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken, object state)
|
private Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken, object state)
|
||||||
{
|
{
|
||||||
|
if (_stopped)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException("RequestStream has been disposed");
|
||||||
|
}
|
||||||
|
|
||||||
var tcs = new TaskCompletionSource<int>(state);
|
var tcs = new TaskCompletionSource<int>(state);
|
||||||
var task = _body.ReadAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken);
|
var task = _body.ReadAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken);
|
||||||
task.ContinueWith((task2, state2) =>
|
task.ContinueWith((task2, state2) =>
|
||||||
|
|
@ -102,5 +118,10 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void StopAcceptingReads()
|
||||||
|
{
|
||||||
|
_stopped = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
class FrameResponseStream : Stream
|
class FrameResponseStream : Stream
|
||||||
{
|
{
|
||||||
private readonly FrameContext _context;
|
private readonly FrameContext _context;
|
||||||
|
private bool _stopped;
|
||||||
|
|
||||||
public FrameResponseStream(FrameContext context)
|
public FrameResponseStream(FrameContext context)
|
||||||
{
|
{
|
||||||
|
|
@ -35,11 +36,21 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
public override void Flush()
|
public override void Flush()
|
||||||
{
|
{
|
||||||
|
if (_stopped)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException("ResponseStream has been disposed");
|
||||||
|
}
|
||||||
|
|
||||||
_context.FrameControl.Flush();
|
_context.FrameControl.Flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task FlushAsync(CancellationToken cancellationToken)
|
public override Task FlushAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
if (_stopped)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException("ResponseStream has been disposed");
|
||||||
|
}
|
||||||
|
|
||||||
return _context.FrameControl.FlushAsync(cancellationToken);
|
return _context.FrameControl.FlushAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,12 +71,27 @@ namespace Microsoft.AspNet.Server.Kestrel.Http
|
||||||
|
|
||||||
public override void Write(byte[] buffer, int offset, int count)
|
public override void Write(byte[] buffer, int offset, int count)
|
||||||
{
|
{
|
||||||
|
if (_stopped)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException("ResponseStream has been disposed");
|
||||||
|
}
|
||||||
|
|
||||||
_context.FrameControl.Write(new ArraySegment<byte>(buffer, offset, count));
|
_context.FrameControl.Write(new ArraySegment<byte>(buffer, offset, count));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
if (_stopped)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException("ResponseStream has been disposed");
|
||||||
|
}
|
||||||
|
|
||||||
return _context.FrameControl.WriteAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken);
|
return _context.FrameControl.WriteAsync(new ArraySegment<byte>(buffer, offset, count), cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void StopAcceptingWrites()
|
||||||
|
{
|
||||||
|
_stopped = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue