未验证 提交 28646107 编写于 作者: S Stephen Toub 提交者: GitHub

Add a Sockets test to validate undesired blocking of continuations (#1973)

We go out of our way (e.g. on Unix queueing work off of the epoll threads) to ensure that arbitrary user code running as part of socket continuations doesn't block those threads and potentially deadlock.  Add a test to help validate this.
上级 8861275a
......@@ -1770,7 +1770,53 @@ public async Task DisposedSocket_ThrowsOperationCanceledException()
}
}
}
[Fact]
public async Task BlockingAsyncContinuations_OperationsStillCompleteSuccessfully()
{
if (UsesSync) return;
using (var listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
listener.BindToAnonymousPort(IPAddress.Loopback);
listener.Listen(1);
await client.ConnectAsync(listener.LocalEndPoint);
using (Socket server = await listener.AcceptAsync())
{
await Task.Run(async delegate // escape the xunit sync context / task scheduler
{
const int SendDelayMs = 100;
Task sendTask = Task.Delay(SendDelayMs)
.ContinueWith(_ => server.SendAsync(new byte[1], SocketFlags.None))
.Unwrap();
await client.ReceiveAsync(new byte[1], SocketFlags.None);
sendTask.GetAwaiter().GetResult(); // should have already completed
// We may now be executing here as part of the continuation invoked synchronously
// when the client ReceiveAsync task was completed. Validate that if socket callbacks block
// (undesirably), other operations on that socket can still be processed.
var mre = new ManualResetEventSlim();
sendTask = Task.Delay(SendDelayMs)
.ContinueWith(_ => server.SendAsync(new byte[1], SocketFlags.None))
.Unwrap();
Task receiveTask = client
.ReceiveAsync(new byte[1], SocketFlags.None)
.ContinueWith(t => { mre.Set(); return t; }, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default)
.Unwrap();
mre.Wait(); // block waiting for other operations on this socket to complete
sendTask.GetAwaiter().GetResult();
await sendTask;
await receiveTask;
});
}
}
}
}
public sealed class SendReceiveMemoryNativeTask : SendReceive<SocketHelperMemoryNativeTask>
{
public SendReceiveMemoryNativeTask(ITestOutputHelper output) : base(output) { }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册