Conversation
|
|
||
| /// <summary>Initializes the <see cref="DebuggerNonUserCodeAttribute"/>.</summary> | ||
| /// <param name="stackTraceOptions">The <see cref="StackTraceFormattingOptions"/> hint.</param> | ||
| internal DebuggerNonUserCodeAttribute(StackTraceFormattingOptions stackTraceOptions) |
There was a problem hiding this comment.
Would need corresponding change in corert as not in shared partition (or moving to shared partition and type in corert removed)
|
More terse stack trace output Rather than the less terse current version |
|
Added api request to make the changes public and for wider use https://github.com/dotnet/corefx/issues/24796 |
00fc7f0 to
4e8e72a
Compare
|
Corert change for moving (some) Debugger attributes to shared partition dotnet/corert#4774 |
|
A couple of things I'm not fan of:
I'd prefer the following API: namespace System.Diagnostics
{
[Flags]
public enum StackTraceFormat
{
Default = 0,
ExcludeNonUserCode = 1 << 0,
ExcludeDispatchBoundaries = 1 << 1
}
public class StackTrace
{
// New overload:
public string ToString(StackTraceFormat format) { ... }
// Existing overload - no change in behavior
public string ToString() => ToString(StackTraceFormat.Default);
}
}and maybe: namespace System
{
public class Exception
{
string ToString(StackTraceFormat format);
}
}Although one can get a stack trace from exception like so: |
But then there wouldn't be a way to set the default, which is used by |
With ToString() => ToString(StackTraceFormat.ExcludeNonUserCode | StackTraceFormat.ExcludeDispatchBoundaries) Then would be a breaking(ish) change on If its only for the string overload; then it would need an additional |
|
@benaadams I'm not proposing that. My proposal is: |
|
@aelij I have updated my comment to add |
|
@benaadams Updated my proposal to make it clear. |
|
@tmat doesn't that render this change largely pointless? The aim is to change the default behaviour |
|
@benaadams No it's not pointless. I don't think we can change the default behavior without breaking things. Frameworks that communicate errors to users that include stack traces can use the new API (e.g. test frameworks, loggers, etc.). |
|
Also, we can start with explicit API and then add global App.config switch that allows users to opt-in (change the global default) without changing their app code. |
What are you concerned about breaking? Relying on the exact frames that show up in a stack trace string from an exception is super brittle, changes based on optimizations applied, etc. |
As shown in #14564 I can erase all these stack traces anyway by changing the code where the exception is thrown (rather than the stack traces). So saying it can't be changed means no new private functions can be renamed or way they call each other changed. As a lot of the functions flow have already changed; using span and memory overloads internally, those would then also be breaking changes by this definition. |
|
Someone will be broken for sure. If we decide we don't care about those cases that's fine. The value of the default is an orthogonal discussion. Let's add an explicit API first then we can discuss what the default should be. |
More so than from various refactorings? Why? I believe the answer is "no", given that Ben already demonstrated he can achieve the same output just by refactoring.
Why? As you say, they're orthogonal. I don't see why we need to hold up one over the other. |
Because the attribute is not applied only on internal helpers we change, but users may have it on other code, including public API and methods marked with no inlining as well.
Fair point. We can indeed discuss in parallel, just wanted to separate one from the other. Explicit API seems to be useful and less controversial to me. |
Not if we use the internal only attribute for now, like the previous version had. That's the one we should go with for now, and stop complicating this. If public API is exposed, a different attribute can be used then. |
|
@stephentoub OK, I guess I missed the point of this change. If you just want to hide a few internal Framework methods then we can do whatever. I though we are designing something applicable more generally. If that's not the case then I don't think why we need to have any formatting options. Just put the attribute on the helpers and filter them out without any options. |
Which is why it should either be a different attribute or an additional parameter. The issue isn't non-user code stack frames; its stack frames that are not part of the error. This code isn't run until after the exception is thrown; its nothing to do with the error - it helps nothing with diagnostics - it is literally noise: This code is after the error, its just factored out into a separate throw helper to avoid bloating the generic code Is all post-error frames which are being filtered out |
|
@benaadams If you are only trying to address the issue with async then why do we need an attribute at all? Can't we just hide all frames from TaskAwaiter type? |
|
Also hiding and anything in the |
Will revert |
|
The same thing. That can be all easily hard coded in a helper method that checks for 3 declaring types. |
|
8 types
Also for the awaiters its only certain methods (the ones that happen post-exception) that should be filtered. Its already missing some for |
|
@benaadams Fair enough, internal attribute distinct from DebuggerNonUserCodeAttribute is a fine solution that addresses the very specific task of removing these helper frames from stack trace strings. Perhaps we can mark the methods/types by both attributes. I was hoping though that we could add public API on StackTrace that would remove all "non user code" frames, so that this stack clean up isn't limited only to CoreFX libraries. I guess we can pursue that another time. |
It's missing those that were added after this code was written. Having the special attribute won't fix it for scripting, since this code is not in CoreFX thus can't use an internal attribute. |
API request might be a good place to follow up https://github.com/dotnet/corefx/issues/24796 |
|
|
Clean follow up to #14608
Adds extra .ctor overload + param to
DebuggerNonUserCodeAttributeAdds StackTrace configuration overrides (for back-compat/runtime switching)
As shown in #14564 similar can be achieved by altering the call chain and the Jit inlines sometimes and doesn't others so what's seen varies - so would only be breaking change if a dependency was taken on the names of private functions in coreclr and the order in which they were called; and then depending on it via
Exception.ToString()- at which point pretty much all changes (i.e. internal implementation changes) become breaking?/cc @tmat @JamesNK @aelij @stephentoub @noahfalk @jkotas PTAL