From 4587a0fc95a0c6de4f4b2da6c3534f53b7bc2fe4 Mon Sep 17 00:00:00 2001 From: Stephen Halter Date: Mon, 29 Aug 2016 12:14:19 -0700 Subject: [PATCH] Prevent possible deadlocks when using MockLibuv.OnPostTask --- .../TestHelpers/MockLibuv.cs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.AspNetCore.Server.KestrelTests/TestHelpers/MockLibuv.cs b/test/Microsoft.AspNetCore.Server.KestrelTests/TestHelpers/MockLibuv.cs index a832fbdf9f..a2e34385ad 100644 --- a/test/Microsoft.AspNetCore.Server.KestrelTests/TestHelpers/MockLibuv.cs +++ b/test/Microsoft.AspNetCore.Server.KestrelTests/TestHelpers/MockLibuv.cs @@ -12,8 +12,10 @@ namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers { private UvAsyncHandle _postHandle; private uv_async_cb _onPost; - private TaskCompletionSource _onPostTcs; - private object _postLock = new object(); + + private readonly object _postLock = new object(); + private TaskCompletionSource _onPostTcs = new TaskCompletionSource(); + private bool _completedOnPostTcs; private bool _stopLoop; private readonly ManualResetEventSlim _loopWh = new ManualResetEventSlim(); @@ -37,9 +39,10 @@ namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers { lock (_postLock) { - if (_onPostTcs == null || _onPostTcs.Task.IsCompleted) + if (_completedOnPostTcs) { _onPostTcs = new TaskCompletionSource(); + _completedOnPostTcs = false; } PostCount++; @@ -64,13 +67,23 @@ namespace Microsoft.AspNetCore.Server.KestrelTests.TestHelpers { _loopWh.Wait(); KestrelThreadBlocker.Wait(); + TaskCompletionSource onPostTcs; lock (_postLock) { _loopWh.Reset(); _onPost(_postHandle.InternalGetHandle()); - _onPostTcs.TrySetResult(null); + + // Ensure any subsequent calls to uv_async_send + // create a new _onPostTcs to be completed. + onPostTcs = _onPostTcs; + _completedOnPostTcs = true; } + + // Calling TrySetResult outside the lock to avoid deadlock + // when the code attempts to call uv_async_send after awaiting + // OnPostTask. + onPostTcs.TrySetResult(null); } return 0;