Skip to content

Commit

Permalink
Fix infinite timeout passed to CancellationTokenSource.CancelAfter (#…
Browse files Browse the repository at this point in the history
…84009)

The recent change to introduce ITimer broke CTS.CancelAfter(Timeout.InfiniteTimeSpan).  The TimeSpan's milliseconds were extracted as a uint but then ended up being cast to a long, such that rather than representing -1 milliseconds, it represented 4294967295 milliseconds.  With the uint representation in Timer, Timeout.UnsignedInfinite needs to be special-cased.
  • Loading branch information
stephentoub committed Mar 28, 2023
1 parent ed921ee commit 3231e4f
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,9 @@ private void CancelAfter(uint millisecondsDelay)
}
}

timer.Change(TimeSpan.FromMilliseconds(millisecondsDelay), Timeout.InfiniteTimeSpan);
timer.Change(
millisecondsDelay == Timeout.UnsignedInfinite ? Timeout.InfiniteTimeSpan : TimeSpan.FromMilliseconds(millisecondsDelay),
Timeout.InfiniteTimeSpan);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,32 @@ public static void CancellationTokenSourceWithTimer_Negative()
Assert.Throws<ObjectDisposedException>(() => { cts.CancelAfter(reasonableTimeSpan); });
}

[Fact]
public static void CancellationTokenSourceWithTimer_SupportsInfinite()
{
var cts = new CancellationTokenSource(TimeSpan.FromDays(1));
Assert.False(cts.IsCancellationRequested);

cts.CancelAfter(Timeout.InfiniteTimeSpan);
Assert.False(cts.IsCancellationRequested);

Assert.True(cts.TryReset());

cts.CancelAfter(TimeSpan.FromDays(1));
Assert.False(cts.IsCancellationRequested);

cts.CancelAfter(Timeout.Infinite);
Assert.False(cts.IsCancellationRequested);

Assert.True(cts.TryReset());

cts = new CancellationTokenSource(Timeout.InfiniteTimeSpan);
Assert.False(cts.IsCancellationRequested);

cts = new CancellationTokenSource(Timeout.Infinite);
Assert.False(cts.IsCancellationRequested);
}

[Fact]
public static void CancellationTokenSource_TryReset_ReturnsFalseIfAlreadyCanceled()
{
Expand Down

0 comments on commit 3231e4f

Please sign in to comment.