Permalink
Browse files

Fix race condition in TaskHelpersExtensions.Catch

  • Loading branch information...
1 parent 590ee02 commit 507866de048f0ce4179d82c992f4066ee8fe1f17 @bradwilson bradwilson committed Apr 4, 2012
Showing with 13 additions and 8 deletions.
  1. +13 −8 src/Common/TaskHelpersExtensions.cs
@@ -21,6 +21,7 @@ internal static class TaskHelpersExtensions
/// </summary>
internal static Task Catch(this Task task, Func<CatchInfo, CatchInfo.CatchResult> continuation, CancellationToken cancellationToken = default(CancellationToken))
{
+ // Fast path for successful tasks, to prevent an extra TCS allocation
if (task.Status == TaskStatus.RanToCompletion)
{
return task;
@@ -40,10 +41,12 @@ internal static Task Catch(this Task task, Func<CatchInfo, CatchInfo.CatchResult
/// </summary>
internal static Task<TResult> Catch<TResult>(this Task<TResult> task, Func<CatchInfo<TResult>, CatchInfo<TResult>.CatchResult> continuation, CancellationToken cancellationToken = default(CancellationToken))
{
+ // Fast path for successful tasks, to prevent an extra TCS allocation
if (task.Status == TaskStatus.RanToCompletion)
{
return task;
}
+
return task.CatchImpl(() => continuation(new CatchInfo<TResult>(task)).Task, cancellationToken);
}
@@ -55,8 +58,6 @@ private static Task<TResult> CatchImpl<TResult>(this Task task, Func<Task<TResul
// Stay on the same thread if we can
if (task.IsCompleted)
{
- Contract.Assert(task.IsFaulted || task.IsCanceled); // caller ensures
-
if (task.IsFaulted)
{
try
@@ -80,8 +81,12 @@ private static Task<TResult> CatchImpl<TResult>(this Task task, Func<Task<TResul
{
return TaskHelpers.Canceled<TResult>();
}
-
- Contract.Assert(task.Status != TaskStatus.RanToCompletion);
+ if (task.Status == TaskStatus.RanToCompletion)
+ {
+ TaskCompletionSource<TResult> tcs = new TaskCompletionSource<TResult>();
+ tcs.TrySetFromTask(task);
+ return tcs.Task;
+ }
}
// Split into a continuation method so that we don't create a closure unnecessarily
@@ -242,7 +247,7 @@ internal static Task Finally(this Task task, Action continuation)
{
// Stay on the same thread if we can
if (task.IsCompleted)
- {
+ {
try
{
continuation();
@@ -251,7 +256,7 @@ internal static Task Finally(this Task task, Action continuation)
catch (Exception ex)
{
return TaskHelpers.FromError(ex);
- }
+ }
}
// Split into a continuation method so that we don't create a closure unnecessarily
@@ -267,7 +272,7 @@ internal static Task<TResult> Finally<TResult>(this Task<TResult> task, Action c
{
// Stay on the same thread if we can
if (task.IsCompleted)
- {
+ {
try
{
continuation();
@@ -276,7 +281,7 @@ internal static Task<TResult> Finally<TResult>(this Task<TResult> task, Action c
catch (Exception ex)
{
return TaskHelpers.FromError<TResult>(ex);
- }
+ }
}
// Split into a continuation method so that we don't create a closure unnecessarily

0 comments on commit 507866d

Please sign in to comment.