Fix MockLibuv.OnPostTask (#2260)

Prevents UvWriteReq leaks in LibuvOutputConsumerTests
This commit is contained in:
Stephen Halter 2018-01-18 15:53:46 -08:00 committed by GitHub
parent cf371a4e74
commit 040ea2e6b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 14 additions and 38 deletions

View File

@ -16,7 +16,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
private readonly object _postLock = new object();
private TaskCompletionSource<object> _onPostTcs = new TaskCompletionSource<object>();
private bool _completedOnPostTcs;
private bool _sendCalled;
private bool _stopLoop;
private readonly ManualResetEventSlim _loopWh = new ManualResetEventSlim();
@ -38,29 +37,17 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
_uv_async_send = postHandle =>
{
// Attempt to run the async send logic inline; this should succeed most of the time.
// In the rare cases where it fails to acquire the lock, use Task.Run() so this call
// never blocks, since the real libuv never blocks.
if (Monitor.TryEnter(_postLock))
lock (_postLock)
{
try
if (_completedOnPostTcs)
{
UvAsyncSend();
_onPostTcs = new TaskCompletionSource<object>();
_completedOnPostTcs = false;
}
finally
{
Monitor.Exit(_postLock);
}
}
else
{
Task.Run(() =>
{
lock (_postLock)
{
UvAsyncSend();
}
});
PostCount++;
_loopWh.Set();
}
return 0;
@ -83,13 +70,16 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
lock (_postLock)
{
_sendCalled = false;
_loopWh.Reset();
_onPost(_postHandle.InternalGetHandle());
}
_onPost(_postHandle.InternalGetHandle());
lock (_postLock)
{
// Allow the loop to be run again before completing
// _onPostTcs given a nested uv_async_send call.
if (!_sendCalled)
if (!_loopWh.IsSet)
{
// Ensure any subsequent calls to uv_async_send
// create a new _onPostTcs to be completed.
@ -171,19 +161,5 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.Tests.TestHelpers
{
return OnWrite(handle, nbufs, status => cb(req.InternalGetHandle(), status));
}
private void UvAsyncSend()
{
if (_completedOnPostTcs)
{
_onPostTcs = new TaskCompletionSource<object>();
_completedOnPostTcs = false;
}
PostCount++;
_sendCalled = true;
_loopWh.Set();
}
}
}