Hide post exception stack frames (#14652)
authorBen Adams <thundercat@illyriad.co.uk>
Mon, 23 Oct 2017 00:39:35 +0000 (01:39 +0100)
committerJan Kotas <jkotas@microsoft.com>
Mon, 23 Oct 2017 00:39:35 +0000 (17:39 -0700)
src/mscorlib/shared/System.Private.CoreLib.Shared.projitems
src/mscorlib/shared/System/Diagnostics/StackTraceHiddenAttribute.cs [new file with mode: 0644]
src/mscorlib/shared/System/Runtime/CompilerServices/ConfiguredValueTaskAwaitable.cs
src/mscorlib/shared/System/Runtime/CompilerServices/ValueTaskAwaiter.cs
src/mscorlib/src/System/Diagnostics/Stacktrace.cs
src/mscorlib/src/System/Runtime/CompilerServices/TaskAwaiter.cs
src/mscorlib/src/System/Runtime/ExceptionServices/ExceptionServicesCommon.cs
src/mscorlib/src/System/ThrowHelper.cs

index 8ba010b..62b683c 100644 (file)
@@ -97,6 +97,7 @@
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\CodeAnalysis\SuppressMessageAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\ConditionalAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Debug.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\StackTraceHiddenAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\DivideByZeroException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\DllNotFoundException.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Double.cs" />
diff --git a/src/mscorlib/shared/System/Diagnostics/StackTraceHiddenAttribute.cs b/src/mscorlib/shared/System/Diagnostics/StackTraceHiddenAttribute.cs
new file mode 100644 (file)
index 0000000..474274a
--- /dev/null
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Diagnostics
+{
+    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Struct, Inherited = false)]
+    internal sealed class StackTraceHiddenAttribute : Attribute
+    {
+        public StackTraceHiddenAttribute() { }
+    }
+}
index 0784e61..0719118 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Diagnostics;
 using System.Runtime.InteropServices;
 using System.Threading.Tasks;
 
@@ -54,6 +55,7 @@ namespace System.Runtime.CompilerServices
             public bool IsCompleted => _value.IsCompleted;
 
             /// <summary>Gets the result of the ValueTask.</summary>
+            [StackTraceHidden]
             public TResult GetResult() =>
                 _value._task == null ? 
                     _value._result : 
index 30e688e..203039a 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Diagnostics;
 using System.Runtime.InteropServices;
 using System.Threading.Tasks;
 
@@ -21,6 +22,7 @@ namespace System.Runtime.CompilerServices
         public bool IsCompleted => _value.IsCompleted;
 
         /// <summary>Gets the result of the ValueTask.</summary>
+        [StackTraceHidden]
         public TResult GetResult() =>
             _value._task == null ? 
                 _value._result : 
index 022c72c..e258839 100644 (file)
@@ -537,7 +537,8 @@ namespace System.Diagnostics
             {
                 StackFrame sf = GetFrame(iFrameIndex);
                 MethodBase mb = sf.GetMethod();
-                if (mb != null)
+                if (mb != null && (ShowInStackTrace(mb) || 
+                                   (iFrameIndex == m_iNumOfFrames - 1))) // Don't filter last frame
                 {
                     // We want a newline at the end of every line except for the last
                     if (fFirstFrame)
@@ -657,6 +658,12 @@ namespace System.Diagnostics
             return sb.ToString();
         }
 
+        private static bool ShowInStackTrace(MethodBase mb)
+        {
+            Debug.Assert(mb != null);
+            return !(mb.IsDefined(typeof(StackTraceHiddenAttribute)) || (mb.DeclaringType?.IsDefined(typeof(StackTraceHiddenAttribute)) ?? false));
+        }
+
         // This helper is called from within the EE to construct a string representation
         // of the current stack trace.
         private static String GetManagedStackTraceStringHelper(bool fNeedFileInfo)
index e13f05f..197de23 100644 (file)
@@ -103,6 +103,7 @@ namespace System.Runtime.CompilerServices
         /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
         /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
         /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+        [StackTraceHidden]
         public void GetResult()
         {
             ValidateEnd(m_task);
@@ -113,6 +114,7 @@ namespace System.Runtime.CompilerServices
         /// prior to completing the await.
         /// </summary>
         /// <param name="task">The awaited task.</param>
+        [StackTraceHidden]
         internal static void ValidateEnd(Task task)
         {
             // Fast checks that can be inlined.
@@ -129,6 +131,7 @@ namespace System.Runtime.CompilerServices
         /// the await on the task, and throws an exception if the task did not complete successfully.
         /// </summary>
         /// <param name="task">The awaited task.</param>
+        [StackTraceHidden]
         private static void HandleNonSuccessAndDebuggerNotification(Task task)
         {
             // NOTE: The JIT refuses to inline ValidateEnd when it contains the contents
@@ -152,6 +155,7 @@ namespace System.Runtime.CompilerServices
         }
 
         /// <summary>Throws an exception to handle a task that completed in a state other than RanToCompletion.</summary>
+        [StackTraceHidden]
         private static void ThrowForNonSuccess(Task task)
         {
             Debug.Assert(task.IsCompleted, "Task must have been completed by now.");
@@ -365,6 +369,7 @@ namespace System.Runtime.CompilerServices
         /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
         /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
         /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+        [StackTraceHidden]
         public TResult GetResult()
         {
             TaskAwaiter.ValidateEnd(m_task);
@@ -469,6 +474,7 @@ namespace System.Runtime.CompilerServices
             /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
             /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
             /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+            [StackTraceHidden]
             public void GetResult()
             {
                 TaskAwaiter.ValidateEnd(m_task);
@@ -557,6 +563,7 @@ namespace System.Runtime.CompilerServices
             /// <exception cref="System.NullReferenceException">The awaiter was not properly initialized.</exception>
             /// <exception cref="System.Threading.Tasks.TaskCanceledException">The task was canceled.</exception>
             /// <exception cref="System.Exception">The task completed in a Faulted state.</exception>
+            [StackTraceHidden]
             public TResult GetResult()
             {
                 TaskAwaiter.ValidateEnd(m_task);
index 8d5ced0..0a37966 100644 (file)
@@ -16,6 +16,7 @@
 =============================================================================*/
 
 using System;
+using System.Diagnostics;
 
 namespace System.Runtime.ExceptionServices
 {
@@ -123,6 +124,7 @@ namespace System.Runtime.ExceptionServices
         // This method will restore the original stack trace and bucketing details before throwing
         // the exception so that it is easy, from debugging standpoint, to understand what really went wrong on
         // the original thread.
+        [StackTraceHidden]
         public void Throw()
         {
             // Restore the exception dispatch details before throwing the exception.
index 68eff51..d3356ea 100644 (file)
@@ -42,6 +42,7 @@ using System.Diagnostics;
 
 namespace System
 {
+    [StackTraceHidden]
     internal static class ThrowHelper
     {
         internal static void ThrowArrayTypeMismatchException()