Skip to content
This repository has been archived by the owner on Dec 18, 2018. It is now read-only.

Commit

Permalink
Turn off synchronous IO by default
Browse files Browse the repository at this point in the history
  • Loading branch information
halter73 committed Jun 28, 2017
1 parent 3fcd909 commit 5b0741f
Show file tree
Hide file tree
Showing 15 changed files with 149 additions and 99 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public partial class Frame : IFeatureCollection,
IHttpConnectionFeature,
IHttpRequestLifetimeFeature,
IHttpRequestIdentifierFeature,
IHttpBodyControlFeature,
IHttpMaxRequestBodySizeFeature,
IHttpRequestBodyMinimumDataRateFeature
{
Expand Down Expand Up @@ -205,6 +206,12 @@ string IHttpRequestIdentifierFeature.TraceIdentifier
set => TraceIdentifier = value;
}

bool IHttpBodyControlFeature.AllowSynchronousIO
{
get => AllowSynchronousIO;
set => AllowSynchronousIO = value;
}

bool IHttpMaxRequestBodySizeFeature.IsReadOnly => HasStartedConsumingRequestBody || _wasUpgraded;

long? IHttpMaxRequestBodySizeFeature.MaxRequestBodySize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public partial class Frame
private static readonly Type ISessionFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.ISessionFeature);
private static readonly Type IHttpMaxRequestBodySizeFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpMaxRequestBodySizeFeature);
private static readonly Type IHttpRequestBodyMinimumDataRateFeatureType = typeof(global::Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttpRequestBodyMinimumDataRateFeature);
private static readonly Type IHttpBodyControlFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpBodyControlFeature);
private static readonly Type IHttpSendFileFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature);

private object _currentIHttpRequestFeature;
Expand All @@ -44,6 +45,7 @@ public partial class Frame
private object _currentISessionFeature;
private object _currentIHttpMaxRequestBodySizeFeature;
private object _currentIHttpRequestBodyMinimumDataRateFeature;
private object _currentIHttpBodyControlFeature;
private object _currentIHttpSendFileFeature;

private void FastReset()
Expand All @@ -56,6 +58,7 @@ private void FastReset()
_currentIHttpConnectionFeature = this;
_currentIHttpMaxRequestBodySizeFeature = this;
_currentIHttpRequestBodyMinimumDataRateFeature = this;
_currentIHttpBodyControlFeature = this;

_currentIServiceProvidersFeature = null;
_currentIHttpAuthenticationFeature = null;
Expand Down Expand Up @@ -139,6 +142,10 @@ internal object FastFeatureGet(Type key)
{
return _currentIHttpRequestBodyMinimumDataRateFeature;
}
if (key == IHttpBodyControlFeatureType)
{
return _currentIHttpBodyControlFeature;
}
if (key == IHttpSendFileFeatureType)
{
return _currentIHttpSendFileFeature;
Expand Down Expand Up @@ -235,6 +242,11 @@ internal void FastFeatureSet(Type key, object feature)
_currentIHttpRequestBodyMinimumDataRateFeature = feature;
return;
}
if (key == IHttpBodyControlFeatureType)
{
_currentIHttpBodyControlFeature = feature;
return;
}
if (key == IHttpSendFileFeatureType)
{
_currentIHttpSendFileFeature = feature;
Expand Down Expand Up @@ -313,6 +325,10 @@ private IEnumerable<KeyValuePair<Type, object>> FastEnumerable()
{
yield return new KeyValuePair<Type, object>(IHttpRequestBodyMinimumDataRateFeatureType, _currentIHttpRequestBodyMinimumDataRateFeature as global::Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttpRequestBodyMinimumDataRateFeature);
}
if (_currentIHttpBodyControlFeature != null)
{
yield return new KeyValuePair<Type, object>(IHttpBodyControlFeatureType, _currentIHttpBodyControlFeature as global::Microsoft.AspNetCore.Http.Features.IHttpBodyControlFeature);
}
if (_currentIHttpSendFileFeature != null)
{
yield return new KeyValuePair<Type, object>(IHttpSendFileFeatureType, _currentIHttpSendFileFeature as global::Microsoft.AspNetCore.Http.Features.IHttpSendFileFeature);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ public Frame(FrameContext frameContext)
public string ConnectionIdFeature { get; set; }
public bool HasStartedConsumingRequestBody { get; set; }
public long? MaxRequestBodySize { get; set; }
public bool AllowSynchronousIO { get; set; }

/// <summary>
/// The request id. <seealso cref="HttpContext.TraceIdentifier"/>
Expand Down Expand Up @@ -306,7 +307,7 @@ public void InitializeStreams(MessageBody messageBody)
{
if (_frameStreams == null)
{
_frameStreams = new Streams(this);
_frameStreams = new Streams(this, this);
}

(RequestBody, ResponseBody) = _frameStreams.Start(messageBody);
Expand All @@ -330,6 +331,7 @@ public void Reset()

HasStartedConsumingRequestBody = false;
MaxRequestBodySize = ServerOptions.Limits.MaxRequestBodySize;
AllowSynchronousIO = ServerOptions.AllowSynchronousIO;
TraceIdentifier = null;
Scheme = null;
Method = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.Internal;
using Microsoft.AspNetCore.Http.Features;

namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{
internal class FrameRequestStream : ReadOnlyStream
{
private readonly IHttpBodyControlFeature _bodyControl;
private MessageBody _body;
private FrameStreamState _state;
private Exception _error;

public FrameRequestStream()
public FrameRequestStream(IHttpBodyControlFeature bodyControl)
{
_bodyControl = bodyControl;
_state = FrameStreamState.Closed;
}

Expand All @@ -34,13 +37,12 @@ public override long Position

public override void Flush()
{
// No-op.
throw new NotSupportedException();
}

public override Task FlushAsync(CancellationToken cancellationToken)
{
// No-op.
return Task.CompletedTask;
throw new NotSupportedException();
}

public override long Seek(long offset, SeekOrigin origin)
Expand All @@ -55,8 +57,12 @@ public override void SetLength(long value)

public override int Read(byte[] buffer, int offset, int count)
{
// ValueTask uses .GetAwaiter().GetResult() if necessary
return ReadAsync(buffer, offset, count).Result;
if (!_bodyControl.AllowSynchronousIO)
{
throw new InvalidOperationException("Synchronous operations are disallowed. Call ReadAsync or set AllowSynchronousIO to true instead.");
}

return ReadAsync(buffer, offset, count).GetAwaiter().GetResult();
}

public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.AspNetCore.Http.Features;

namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http
{
internal class FrameResponseStream : WriteOnlyStream
{
private IFrameControl _frameControl;
private readonly IHttpBodyControlFeature _bodyControl;
private readonly IFrameControl _frameControl;
private FrameStreamState _state;

public FrameResponseStream(IFrameControl frameControl)
public FrameResponseStream(IHttpBodyControlFeature bodyControl, IFrameControl frameControl)
{
_bodyControl = bodyControl;
_frameControl = frameControl;
_state = FrameStreamState.Closed;
}
Expand All @@ -31,6 +34,7 @@ public override long Position
set => throw new NotSupportedException();
}

// REVIEW: Should Flush() throw?
public override void Flush()
{
FlushAsync(default(CancellationToken)).GetAwaiter().GetResult();
Expand Down Expand Up @@ -58,6 +62,11 @@ public override void SetLength(long value)

public override void Write(byte[] buffer, int offset, int count)
{
if (!_bodyControl.AllowSynchronousIO)
{
throw new InvalidOperationException("Synchronous operations are disallowed. Call WriteAsync or set AllowSynchronousIO to true instead.");
}

WriteAsync(buffer, offset, count, default(CancellationToken)).GetAwaiter().GetResult();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.IO;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http;

namespace Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure
Expand All @@ -17,11 +18,11 @@ private static readonly ThrowingWriteOnlyStream _throwingResponseStream
private readonly FrameRequestStream _emptyRequest;
private readonly Stream _upgradeStream;

public Streams(IFrameControl frameControl)
public Streams(IHttpBodyControlFeature bodyControl, IFrameControl frameControl)
{
_request = new FrameRequestStream();
_emptyRequest = new FrameRequestStream();
_response = new FrameResponseStream(frameControl);
_request = new FrameRequestStream(bodyControl);
_emptyRequest = new FrameRequestStream(bodyControl);
_response = new FrameResponseStream(bodyControl, frameControl);
_upgradeableResponse = new WrappingStream(_response);
_upgradeStream = new FrameDuplexStream(_request, _response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ public class KestrelServerOptions
/// <remarks>The default mode is <see cref="SchedulingMode.Default"/></remarks>
public SchedulingMode ApplicationSchedulingMode { get; set; } = SchedulingMode.Default;

/// <summary>
/// Gets or sets a value that controls whether synchronous IO is allowed for the <see cref="Http.Features.IHttpRequestFeature.Body"/> and <see cref="Http.Features.IHttpResponseFeature.Body"/>
/// </summary>
public bool AllowSynchronousIO { get; set; }

/// <summary>
/// Enables the Listen options callback to resolve and use services registered by the application during startup.
/// Typically initialized by UseKestrel()"/>.
Expand Down
Loading

0 comments on commit 5b0741f

Please sign in to comment.