-
-
Notifications
You must be signed in to change notification settings - Fork 109
More Robust Global Timeout Cancellation #4140
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,8 +14,7 @@ public class EngineCancellationToken : IDisposable | |
| /// Gets the cancellation token. | ||
| /// </summary> | ||
| public CancellationToken Token { get; private set; } | ||
|
|
||
| private CancellationTokenSource? _forcefulExitCts; | ||
|
|
||
| private volatile bool _forcefulExitStarted; | ||
|
|
||
| /// <summary> | ||
|
|
@@ -27,6 +26,8 @@ internal void Initialise(CancellationToken cancellationToken) | |
| CancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); | ||
| Token = CancellationTokenSource.Token; | ||
|
|
||
| Token.Register(_ => Cancel(), this); | ||
|
|
||
| // Console.CancelKeyPress is not supported on browser platforms | ||
| #if NET5_0_OR_GREATER | ||
| if (!OperatingSystem.IsBrowser()) | ||
|
|
@@ -38,8 +39,16 @@ internal void Initialise(CancellationToken cancellationToken) | |
| } | ||
| #endif | ||
| } | ||
|
|
||
| private void OnCancelKeyPress(object? sender, ConsoleCancelEventArgs e) | ||
| { | ||
| Cancel(); | ||
|
|
||
| // Prevent the default behavior (immediate termination) | ||
| e.Cancel = true; | ||
| } | ||
|
|
||
| private void Cancel() | ||
| { | ||
| // Cancel the test execution | ||
| if (!CancellationTokenSource.IsCancellationRequested) | ||
|
|
@@ -51,14 +60,9 @@ private void OnCancelKeyPress(object? sender, ConsoleCancelEventArgs e) | |
| if (!_forcefulExitStarted) | ||
| { | ||
| _forcefulExitStarted = true; | ||
|
Comment on lines
60
to
62
|
||
|
|
||
| // Cancel any previous forceful exit timer | ||
| _forcefulExitCts?.Cancel(); | ||
| _forcefulExitCts?.Dispose(); | ||
| _forcefulExitCts = new CancellationTokenSource(); | ||
|
|
||
|
|
||
| // Start a new forceful exit timer | ||
| _ = Task.Delay(TimeSpan.FromSeconds(10), _forcefulExitCts.Token).ContinueWith(t => | ||
| _ = Task.Delay(TimeSpan.FromSeconds(30), CancellationToken.None).ContinueWith(t => | ||
|
||
| { | ||
| if (!t.IsCanceled) | ||
| { | ||
|
|
@@ -67,9 +71,6 @@ private void OnCancelKeyPress(object? sender, ConsoleCancelEventArgs e) | |
| } | ||
| }, TaskScheduler.Default); | ||
| } | ||
|
|
||
| // Prevent the default behavior (immediate termination) | ||
| e.Cancel = true; | ||
| } | ||
|
|
||
| private void OnProcessExit(object? sender, EventArgs e) | ||
|
|
@@ -102,8 +103,6 @@ public void Dispose() | |
| #if NET5_0_OR_GREATER | ||
| } | ||
| #endif | ||
| _forcefulExitCts?.Cancel(); | ||
| _forcefulExitCts?.Dispose(); | ||
| CancellationTokenSource.Dispose(); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Registering a callback that calls Cancel() when the token is cancelled creates a potential issue. When the external cancellation token (passed to Initialise) is cancelled, it will trigger this callback, which calls Cancel(). The Cancel() method then calls CancellationTokenSource.Cancel() on line 56.
While CancellationTokenSource.CreateLinkedTokenSource already propagates cancellation automatically, this explicit registration adds the side effect of starting the forceful exit timer whenever ANY linked token is cancelled. This may be intentional for global timeout scenarios, but it means the forceful exit timer will start even for normal test completion if the parent token is cancelled.
Consider whether this behavior is intended for all cancellation scenarios, or if the forceful exit timer should only start for specific cancellation types (e.g., Ctrl+C). If this is intentional, add a comment explaining why the registration is needed despite the linked token source.