Remove race condition from socket input that could stall reads

- Without the _sync lock, if new data was produced as ConsumingComplete
  was called, the next "await SocketInput" might never complete despite not
  all data being examined.
- If more data is produced afterward, the stall would be prevented, but this
  isn't always the case such as during the end of the request.
This commit is contained in:
Stephen Halter 2016-03-10 09:14:36 -08:00
parent 850632a091
commit 84a68208d0
1 changed files with 82 additions and 72 deletions

View File

@ -28,6 +28,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
private MemoryPoolBlock _pinned; private MemoryPoolBlock _pinned;
private int _consumingState; private int _consumingState;
private object _sync = new object();
public SocketInput(MemoryPool memory, IThreadPool threadPool) public SocketInput(MemoryPool memory, IThreadPool threadPool)
{ {
@ -57,6 +58,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
} }
public void IncomingData(byte[] buffer, int offset, int count) public void IncomingData(byte[] buffer, int offset, int count)
{
lock (_sync)
{ {
if (count > 0) if (count > 0)
{ {
@ -82,8 +85,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
Complete(); Complete();
} }
}
public void IncomingComplete(int count, Exception error) public void IncomingComplete(int count, Exception error)
{
lock (_sync)
{ {
if (_pinned != null) if (_pinned != null)
{ {
@ -117,6 +123,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
Complete(); Complete();
} }
}
public void IncomingDeferred() public void IncomingDeferred()
{ {
@ -161,6 +168,8 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
public void ConsumingComplete( public void ConsumingComplete(
MemoryPoolIterator consumed, MemoryPoolIterator consumed,
MemoryPoolIterator examined) MemoryPoolIterator examined)
{
lock (_sync)
{ {
MemoryPoolBlock returnStart = null; MemoryPoolBlock returnStart = null;
MemoryPoolBlock returnEnd = null; MemoryPoolBlock returnEnd = null;
@ -198,6 +207,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Http
throw new InvalidOperationException("No ongoing consuming operation to complete."); throw new InvalidOperationException("No ongoing consuming operation to complete.");
} }
} }
}
public void CompleteAwaiting() public void CompleteAwaiting()
{ {