Skip to content

Mark custom continuation resumptions as StackTraceHidden#130777

Merged
jakobbotsch merged 2 commits into
dotnet:mainfrom
jakobbotsch:exception-thrown-from-task-stack-trace
Jul 16, 2026
Merged

Mark custom continuation resumptions as StackTraceHidden#130777
jakobbotsch merged 2 commits into
dotnet:mainfrom
jakobbotsch:exception-thrown-from-task-stack-trace

Conversation

@jakobbotsch

Copy link
Copy Markdown
Member

E.g.

public static async Task Main()
{
    Task t = ThrowsSoon();
    try
    {
        await t;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

private static async Task ThrowsSoon()
{
    await Task.Delay(50);
    throw new Exception("Exception thrown");
}
 System.Exception: Exception thrown
    at Program.ThrowsSoon() in C:\dev\dotnet\playground\Program.cs:line 24
-   at System.Runtime.CompilerServices.RuntimeAsyncTaskContinuation.TaskContinuationResume.ResumeTaskContinuation(Continuation cont, Byte& result)
    at Program.Main() in C:\dev\dotnet\playground\Program.cs:line 13

E.g.
```csharp
public static async Task Main()
{
    Task t = ThrowsSoon();
    try
    {
        await t;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
    }
}

private static async Task ThrowsSoon()
{
    await Task.Delay(50);
    throw new Exception("Exception thrown");
}
```

```diff
 System.Exception: Exception thrown
    at Program.ThrowsSoon() in C:\dev\dotnet\playground\Program.cs:line 24
-   at System.Runtime.CompilerServices.RuntimeAsyncTaskContinuation.TaskContinuationResume.ResumeTaskContinuation(Continuation cont, Byte& result)
    at Program.Main() in C:\dev\dotnet\playground\Program.cs:line 13
```
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @dotnet/area-system-reflection
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR hides internal async continuation resumption frames from user-visible exception stack traces by marking the relevant resumption helpers as [StackTraceHidden], and adds tests to ensure those frames no longer appear for both Task and ValueTask/IValueTaskSource continuation paths.

Changes:

  • Mark RuntimeAsyncTaskContinuation.TaskContinuationResume.ResumeTaskContinuation as [StackTraceHidden].
  • Mark AsyncHelpers.ValueTaskSourceContinuation.ValueTaskSourceContinuationResume.ResumeValueTaskSourceContinuation as [StackTraceHidden].
  • Extend StackTraceTests with new async scenarios and assertions that "ResumeTaskContinuation" / "ResumeValueTaskSourceContinuation" are absent from Exception.ToString() output.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs Adds new async test cases (Task + custom IValueTaskSource) and asserts resumption helpers don’t appear in exception text.
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeAsyncTaskContinuation.cs Adds [StackTraceHidden] to the Task continuation resume helper to suppress it from stack traces.
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.ValueTaskSourceContinuation.cs Adds [StackTraceHidden] to the ValueTaskSource continuation resume helper to suppress it from stack traces.

Comment thread src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 15, 2026 13:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

@jakobbotsch

Copy link
Copy Markdown
Member Author

PTAL @rcj1

@jakobbotsch

Copy link
Copy Markdown
Member Author

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@jakobbotsch
jakobbotsch merged commit b78a8f8 into dotnet:main Jul 16, 2026
155 of 159 checks passed
@jakobbotsch
jakobbotsch deleted the exception-thrown-from-task-stack-trace branch July 16, 2026 10:45
BrzVlad added a commit that referenced this pull request Jul 22, 2026
Test added in #130777.

For code like the one below, where the `GetResult` of the value task
source throws, the correct stacktrace should point to the await as the
source of the throw. However, on interpreter, it is pointing to the new
instruction.
```
public static async Task ThrowsSoonValueTaskSource()
{
    ValueTask vt = new ValueTask(new ThrowsSoonValueTaskSourceImpl(), 0);
    await vt;
}
```

The cause of this seems to be that we only report IL->native offsets for
locations where the IL stack is empty, therefore we don't have a
location at the await. This seems to be easily fixable via
BrzVlad@460eae9.
The problem with the fix is that it is a partial revert of
#127469 so it has a good chance to
lead to regressions on other diagnostic tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants