Skip to content

Preserve ExceptionDispatchInfo.SetCurrentStackTrace across throw - #660

Merged
SimonCropp merged 1 commit into
mainfrom
fix/set-current-stack-trace
Oct 11, 2026
Merged

SimonCropp merged 1 commit into
mainfrom
fix/set-current-stack-trace

Conversation

@SimonCropp

Copy link
Copy Markdown
Owner

Bug

The ExceptionDispatchInfo.SetCurrentStackTrace polyfill wrote the captured trace to Exception._stackTraceString. The runtime resets that field when the exception is thrown, so the captured trace was lost as soon as the exception was thrown or surfaced through an await, which is the whole point of the API (e.g. TaskCompletionSource.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(ex))).

Fix

Store the trace the way the BCL does: in _remoteStackTraceString, followed by the "End of stack trace from previous location" marker. The runtime preserves that field across throws and prepends it to Exception.StackTrace. If the field cannot be found, the previous _stackTraceString behaviour is kept as a fallback.

Test

ExceptionDispatchInfoSetCurrentStackTrace_SurvivesThrow and _SurvivesAwait capture the trace in a named NoInlining method, throw / await the exception, and assert the method name is still in StackTrace. Both failed on net48 before the fix; they pass on net462 / net48 (polyfill) and net8.0 / net10.0 (BCL).

@SimonCropp SimonCropp added this to the 11.4.4 milestone Oct 11, 2026
@SimonCropp
SimonCropp merged commit 52c63bf into main Oct 11, 2026
5 checks passed
@SimonCropp
SimonCropp deleted the fix/set-current-stack-trace branch October 11, 2026 22:10
This was referenced Oct 12, 2026
This was referenced Oct 13, 2026
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.

1 participant