Skip to content

Fix TaskCanceledException in TestReporter when ConnectedTask is canceled#1544

Open
rolfbjarne wants to merge 2 commits intodotnet:mainfrom
rolfbjarne:taskcancelationexception
Open

Fix TaskCanceledException in TestReporter when ConnectedTask is canceled#1544
rolfbjarne wants to merge 2 commits intodotnet:mainfrom
rolfbjarne:taskcancelationexception

Conversation

@rolfbjarne
Copy link
Member

When _listener.ConnectedTask is canceled (e.g. due to process timeout),
Task.IsCompleted returns true but accessing .Result throws
TaskCanceledException. This caused numerous test runs to report as
HarnessException instead of reporting their actual result.

Use IsCompletedSuccessfully instead of IsCompleted to guard .Result
access - it only returns true for tasks that ran to completion (not
canceled or faulted).

When _listener.ConnectedTask is canceled (e.g. due to process timeout),
Task.IsCompleted returns true but accessing .Result throws
TaskCanceledException. This caused numerous test runs to report as
HarnessException instead of reporting their actual result.

Use IsCompletedSuccessfully instead of IsCompleted to guard .Result
access - it only returns true for tasks that ran to completion (not
canceled or faulted).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a cancellation edge-case in the iOS shared TestReporter so canceled listener connection tasks don’t throw TaskCanceledException when their Result is accessed, allowing test runs to report the actual outcome instead of failing as a harness error.

Changes:

  • Switches guards from Task.IsCompleted to Task.IsCompletedSuccessfully before reading _listener.ConnectedTask.Result.
  • Applies the same fix both for the “test execution started” check and for the empty run-log launch-failure detection.

Comment on lines +139 to 142
if (!_listener.ConnectedTask.IsCompletedSuccessfully || !_listener.ConnectedTask.Result)
{
_launchFailure = true;
}
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a unit test covering the scenario this change fixes: when ConnectedTask is canceled (e.g., due to a timeout) and the run log is empty, GetPidFromRunLog/CollectSimulatorResult should not throw and should treat it as a launch failure. This will prevent regressions where accessing ConnectedTask.Result reintroduces TaskCanceledException.

Suggested change
if (!_listener.ConnectedTask.IsCompletedSuccessfully || !_listener.ConnectedTask.Result)
{
_launchFailure = true;
}
var connectedTask = _listener.ConnectedTask;
// If the task never completed, or if accessing the result throws (e.g. due to cancellation),
// treat this as a launch failure instead of surfacing TaskCanceledException.
if (!connectedTask.IsCompleted)
{
_launchFailure = true;
}
else
{
bool connected = false;
try
{
connected = connectedTask.Result;
}
catch (AggregateException ae) when (ae.InnerException is TaskCanceledException)
{
connected = false;
}
catch (TaskCanceledException)
{
connected = false;
}
if (!connected)
{
_launchFailure = true;
}
}

Copilot uses AI. Check for mistakes.
Copy link
Member

@vitek-karas vitek-karas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's easy we should add a test, other than that this looks good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants