Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corefx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Köplinger <alex.koeplinger@outlook.com>2018-06-23 04:56:53 +0300
committerAlexander Köplinger <alex.koeplinger@outlook.com>2018-06-25 13:25:01 +0300
commit2d4301a0d697ab0178044bbcd37afd6b59b43a6d (patch)
tree1aec244519832c56aab9d02578c3fa981f9587f8
parentb9709fa283d6f8ddbe5c566cb328bf0cf7e61bf1 (diff)
Fix race in TaskCancelWaitTestCases.TaskCancelWait1() (#30615)
When `CancelChildren` is enabled (currently only in the `TaskCancelWait1` test) we're hitting a race in `TaskCancelWaitTest.CreateTask()`: 1. Let's assume Task A is processing `node` 2. Task A spawns a new Task B for processing `node_1` 3. Task B starts and signals the `_countdownEvent` 4. `RealRun()` on the main thread exits the wait on `_countdownEvent` 5. `RealRun()` calls `Verify()` which loops through all the nodes and calls `VerifyCancel()` 6. We get an assertion because `CancellationToken.IsCancellationRequested` is false 7. Task A continues and sets the CancellationToken, but it is already too late by this point To fix this race we wait on the task in `RealRun()` before proceeding to the verification step. This uncovered another issue: Since `_countdownEvent` is accessed by multiple threads we have another race between checking `_countdownEvent.IsSet` and `_countdownEvent.Signal()`. This caused a `System.InvalidOperationException: Invalid attempt made to decrement the event's count below zero.` Fixed it by locking access to the `_countdownEvent`. Fixes https://github.com/dotnet/corefx/issues/20457 Fixes https://github.com/mono/mono/issues/6920 (cherry picked from commit 69cf791e365c2be6f919929c5ae521b2e070aa5d)
-rw-r--r--src/System.Threading.Tasks/tests/Task/TaskCancelWaitTest.cs18
1 files changed, 13 insertions, 5 deletions
diff --git a/src/System.Threading.Tasks/tests/Task/TaskCancelWaitTest.cs b/src/System.Threading.Tasks/tests/Task/TaskCancelWaitTest.cs
index 5d178dc3c5..5abffea66f 100644
--- a/src/System.Threading.Tasks/tests/Task/TaskCancelWaitTest.cs
+++ b/src/System.Threading.Tasks/tests/Task/TaskCancelWaitTest.cs
@@ -70,6 +70,7 @@ namespace System.Threading.Tasks.Tests.CancelWait
{
case API.Cancel:
_taskTree.CancellationTokenSource.Cancel();
+ _taskTree.Task.Wait();
break;
case API.Wait:
@@ -131,8 +132,11 @@ namespace System.Threading.Tasks.Tests.CancelWait
if (current.IsLeaf)
{
- if (!_countdownEvent.IsSet)
- _countdownEvent.Signal();
+ lock (_countdownEvent)
+ {
+ if (!_countdownEvent.IsSet)
+ _countdownEvent.Signal();
+ }
}
else
{
@@ -162,10 +166,13 @@ namespace System.Threading.Tasks.Tests.CancelWait
}
finally
{
- // stop the tree creation and let the main thread proceed
- if (!_countdownEvent.IsSet)
+ lock (_countdownEvent)
{
- _countdownEvent.Signal(_countdownEvent.CurrentCount);
+ // stop the tree creation and let the main thread proceed
+ if (!_countdownEvent.IsSet)
+ {
+ _countdownEvent.Signal(_countdownEvent.CurrentCount);
+ }
}
}
}
@@ -208,6 +215,7 @@ namespace System.Threading.Tasks.Tests.CancelWait
VerifyCancel(current);
VerifyResult(current);
});
+ Assert.Null(_caughtException);
break;
//root task was calling wait