Skip to content

Commit 08db7a3

Browse files
authored
Skipping EDI in the runtime-async case as well (#128735)
In stacktrace pretty-printing we skip the EDI boundary for async methods, so as not to clutter stacktraces with `--- End of stack trace from previous location ---`. We should do the same for runtime-async. Fixes #128723
1 parent 01cd5cc commit 08db7a3

2 files changed

Lines changed: 34 additions & 2 deletions

File tree

src/libraries/System.Diagnostics.StackTrace/tests/StackTraceTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ public static async Task Test2(int i)
6666
{
6767
throw new NullReferenceException("Exception from Test2");
6868
}
69+
70+
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
71+
[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(false)]
72+
#line 1 "EdiOuter.cs"
73+
public static async Task EdiOuter()
74+
{
75+
await V2Methods.EdiMiddle();
76+
}
6977
}
7078

7179
public class V2Methods
@@ -206,6 +214,22 @@ public static async Task Baz()
206214
if (Random.Shared.Next(1) == 100) await Task.Yield();
207215
throw new Exception("Exception from Baz method.");
208216
}
217+
218+
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
219+
[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(true)]
220+
#line 1 "EdiMiddle.cs"
221+
public static async Task EdiMiddle()
222+
{
223+
await EdiInner();
224+
}
225+
226+
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]
227+
[System.Runtime.CompilerServices.RuntimeAsyncMethodGeneration(true)]
228+
#line 1 "EdiInner.cs"
229+
public static async Task EdiInner()
230+
{
231+
throw new InvalidOperationException("Exception from EdiInner");
232+
}
209233
}
210234
}
211235
#line default
@@ -640,6 +664,12 @@ private static string FileInfoPattern(string fileLinePattern) =>
640664
@"V2Methods\.Baz\(\)" + FileInfoPattern(@".*Baz.*\.cs:line 4"),
641665
@"V2Methods\.Bux\(\)" + FileInfoPattern(@".*Bux.*\.cs:line 6")
642666
}},
667+
{ "EdiOuter", new[] {
668+
@"Exception from EdiInner",
669+
@"V2Methods\.EdiInner\(\)" + FileInfoPattern(@".*EdiInner.*\.cs:line 3"),
670+
@"V2Methods\.EdiMiddle\(\)" + FileInfoPattern(@".*EdiMiddle.*\.cs:line 3"),
671+
@"V1Methods.*EdiOuter"
672+
}},
643673
};
644674

645675
public static IEnumerable<object[]> Ctor_Async_TestData()
@@ -649,6 +679,7 @@ public static IEnumerable<object[]> Ctor_Async_TestData()
649679
yield return new object[] { () => V2Methods.Quux(), MethodExceptionStrings["Quux"] };
650680
yield return new object[] { () => V2Methods.Quuux(), MethodExceptionStrings["Quuux"] };
651681
yield return new object[] { () => V2Methods.Bux(), MethodExceptionStrings["Bux"] };
682+
yield return new object[] { () => V1Methods.EdiOuter(), MethodExceptionStrings["EdiOuter"] };
652683
}
653684

654685
[ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsRuntimeAsyncSupported))]
@@ -677,6 +708,7 @@ public async Task ToString_Async(Func<Task> asyncMethod, string[] expectedPatter
677708
Assert.True(match.Success, $"Could not find expected pattern '{pattern}' in exception text:\n{exceptionText} starting at index {startIndex}.");
678709
startIndex = match.Index + match.Length;
679710
}
711+
Assert.DoesNotContain("--- End of stack trace from previous location ---", exceptionText);
680712
}
681713

682714
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)]

src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,11 @@ internal void ToString(TraceFormat traceFormat, StringBuilder sb)
237237

238238
sb.Append(" ").Append(word_At).Append(' ');
239239

240-
bool isAsync = false;
240+
bool isAsync = (mb.MethodImplementationFlags & MethodImplAttributes.Async) != 0;
241241
Type? declaringType = mb.DeclaringType;
242242
string methodName = mb.Name;
243243
bool methodChanged = false;
244-
if (declaringType != null && IsDefinedSafe(declaringType, typeof(CompilerGeneratedAttribute), inherit: false))
244+
if (!isAsync && declaringType != null && IsDefinedSafe(declaringType, typeof(CompilerGeneratedAttribute), inherit: false))
245245
{
246246
isAsync = declaringType.IsAssignableTo(typeof(IAsyncStateMachine));
247247
if (isAsync || declaringType.IsAssignableTo(typeof(IEnumerator)))

0 commit comments

Comments
 (0)