Skip to content

Commit

Permalink
Schedule tasks with TaskCreationOptions.HideScheduler
Browse files Browse the repository at this point in the history
When Task.Factory.StartNew(...), Task.ContinueWith(...), etc. are used without specifying a TaskScheduler, TaskScheduler.Current is used.  Since tests are being scheduled to a TaskScheduler that wraps the MaxConcurrencySyncContext, that means that if a test itself schedules another task using one of these methods without specifying a scheduler, that task will be scheduled back to the same MaxConcurrencySyncContext.  In some cases that isn't problematic; however, if a synchronous test schedules such a task and then synchronously blocks waiting for such a task to complete, it's possible for the test to deadlock, e.g. if the concurrency level is 1 such that there's only one worker and that worker is blocked in the test waiting for the queued task to complete, but the queued task will never complete because it could only complete if the worker completed executing the blocked task so it could pick up the sub-task.

A solution is to specify the TaskCreationOptions.HideScheduler flag when xunit queues its RunTestCollectionAsync task.  By adding this option, that task will be scheduled to the MaxConcurrencySyncContext scheduler, but inside of that task, TaskScheduler.Current will return TaskScheduler.Default rather than the custom scheduler, such that any tasks user code creates in the test won't be forced back to xunit's scheduler.
  • Loading branch information
stephentoub committed Jan 15, 2015
1 parent 48cf985 commit 2f2efc5
Showing 1 changed file with 1 addition and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ protected override async Task<RunSummary> RunTestCollectionsAsync(IMessageBus me
var tasks = OrderTestCases().Select(
collection => Task.Factory.StartNew(() => RunTestCollectionAsync(messageBus, collection.Item1, collection.Item2, cancellationTokenSource),
cancellationTokenSource.Token,
TaskCreationOptions.DenyChildAttach,
TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler,
scheduler)
).ToArray();

Expand Down

0 comments on commit 2f2efc5

Please sign in to comment.