Fix race condition in Task.WhenAny (#2583)

This commit is contained in:
Stephen Toub 2017-01-25 10:17:54 -05:00 коммит произвёл Jan Kotas
Родитель 9ee2ba750c
Коммит 94216a23f6
1 изменённых файлов: 17 добавлений и 1 удалений

Просмотреть файл

@ -2394,7 +2394,23 @@ namespace System.Threading.Tasks
checkArgsOnly = true;
}
// Otherwise, add the completion action and keep going.
else task.AddCompletionAction(promise);
else
{
task.AddCompletionAction(promise);
if (promise.IsCompleted)
{
// One of the previous tasks that already had its continuation registered may have
// raced to complete with our adding the continuation to this task. The completion
// routine would have gone through and removed the continuation from all of the tasks
// with which it was already registered, but if the race causes this continuation to
// be added after that, it'll never be removed. As such, after adding the continuation,
// we check to see whether the promise has already completed, and if it has, we try to
// manually remove the continuation from this task. If it was already removed, it'll be
// a nop, and if we race to remove it, the synchronization in RemoveContinuation will
// keep things consistent.
task.RemoveContinuation(promise);
}
}
}
return promise;