dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.44k stars 10.01k forks source link

Break on first-chance exception in Web Assembly debugger #42510

Open TanayParikh opened 2 years ago

TanayParikh commented 2 years ago

Update: The actual request here is being able to have the debugger break if there's an unhandled exception. Please disregard the stuff about AppDomain.CurrentDomain.UnhandledException.


Original report

Looks like this is an issue impacting the community: https://www.reddit.com/r/Blazor/comments/vhrrl1/blazor_wasm_how_to_break_on_unhandled_exception/

Ideally we can hook into the System.AppDomain.CurrentDomain.UnhandledException as we do with WebView for WinForms / WPF.

Repro:

Index.razor:

<button @onclick="ThrowException">Throw Exception</button>

@code {
    public void ThrowException()
    {
        throw new Exception("throwing new ex");
    }
}

Program.cs:

System.AppDomain.CurrentDomain.UnhandledException += (sender, error) =>
{
    System.Console.WriteLine("!!! Encountered exception !!!");
};

Expected: !!! Encountered exception !!! console output Actual: The exception breaks the world // stack trace dumps to console

Kind of related: https://github.com/dotnet/maui/issues/5535

javiercn commented 2 years ago

@TanayParikh if its about breaking when an exception happens, we shouldn't do anything in the framework for it, "Break for first chance exceptions" is a debugger feature. We should make sure that it works in all platforms.

jasonswearingen commented 2 years ago

Yes the issue described in that reddit post is the inability to break on unhandled exceptions.

TanayParikh commented 2 years ago

if its about breaking when an exception happens, we shouldn't do anything in the framework for it, "Break for first chance exceptions" is a debugger feature.

Yes the issue described in that reddit post is the inability to break on unhandled exceptions.

Just making sure we aren't talking about two different things. I believe @javiercn is saying the framework doesn't have to automatically support breaking on unhandled exceptions using a first chance mechanism like we see with C# in VS.

@jasonswearingen are you perhaps suggesting that it's not possible to manually break on unhandled exceptions at all? In that case, wouldn't a mechanism like System.AppDomain.CurrentDomain.UnhandledException be ideal so that users are able to set breakpoints for unhandled exceptions should they occur?

jasonswearingen commented 2 years ago

@jasonswearingen are you perhaps suggesting that it's not possible to manually break on unhandled exceptions at all? In that case, wouldn't a mechanism like System.AppDomain.CurrentDomain.UnhandledException be ideal so that users are able to set breakpoints for unhandled exceptions should they occur?

Perhaps that is the best workaround for the issue, but I prefer not to speculate, as perhaps setting a breakpoint in a global exception handler might destroy state at the callsite that a proper "break on unhandled exception" would preserve.

javiercn commented 2 years ago

This is a functionality of the debugger, if it doesn't work, we shouldn't workaround anything in the framework. We should report it to the right folks to make sure that the experience is fixed. The instructions below are for VS, but applies to VS Code and VS 4 Mac in the same way.

https://docs.microsoft.com/en-us/visualstudio/debugger/managing-exceptions-with-the-debugger?view=vs-2022#tell-the-debugger-to-break-when-an-exception-is-thrown

ghost commented 2 years ago

Thanks for contacting us. We're moving this issue to the .NET 7 Planning milestone for future evaluation / consideration. Because it's not immediately obvious that this is a bug in our framework, we would like to keep this around to collect more feedback, which can later help us determine the impact of it. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

jasonswearingen commented 2 years ago

@javiercn related, do you know if unhandled exceptions are able to be breakpoint triggered in MAUI Blazor WebView? The description of this issue https://github.com/dotnet/maui/issues/4441 imples that it works, but upon closing it is not clear that this is actually working I ask because I might consider attempting BlazorWebview as a dev workflow if thrown exceptions get too frustrating in the short term

javiercn commented 2 years ago

@jasonswearingen as far as I know works for both exceptions thrown from JS (if you have the dev tools open and configured to break on thrown JS exceptions) and exceptions thrown from .NET if you have configured the .NET debugger to break on them.

TanayParikh commented 2 years ago

This is a functionality of the debugger, if it doesn't work, we shouldn't workaround anything in the framework. We should report it to the right folks to make sure that the experience is fixed.

I've reported it on the VS side here: https://developercommunity.visualstudio.com/t/Blazor-WASM-Debugging-Doesnt-Catch-Unha/10079630

TanayParikh commented 2 years ago

@jasonswearingen I'm not sure what you mean by:

be breakpoint triggered

Generally speaking, unhandled exceptions aren't automatically caught on MAUI. This is being tracked by https://github.com/dotnet/maui/issues/5535.

The first chance exception is raised for Blazor Hybrid apps on WinForms & WPF.

mkArtakMSFT commented 2 years ago

@lewing FYI

ghost commented 2 years ago

Tagging subscribers to 'arch-wasm': @lewing See info in area-owners.md if you want to be subscribed.

Issue Details
Looks like this is an issue impacting the community: https://www.reddit.com/r/Blazor/comments/vhrrl1/blazor_wasm_how_to_break_on_unhandled_exception/ Ideally we can hook into the `System.AppDomain.CurrentDomain.UnhandledException` as we do with WebView for WinForms / WPF. Repro: `Index.razor`: ```razor @code { public void ThrowException() { throw new Exception("throwing new ex"); } } ``` `Program.cs`: ```csharp System.AppDomain.CurrentDomain.UnhandledException += (sender, error) => { System.Console.WriteLine("!!! Encountered exception !!!"); }; ``` Expected: `!!! Encountered exception !!!` console output Actual: The exception breaks the world // stack trace dumps to console Kind of related: https://github.com/dotnet/maui/issues/5535
Author: TanayParikh
Assignees: -
Labels: `arch-wasm`, `blazor-wasm`
Milestone: -
ghost commented 2 years ago

Tagging subscribers to this area: @thaystg See info in area-owners.md if you want to be subscribed.

Issue Details
**Update**: The actual request here is being able to have the debugger break if there's an unhandled exception. Please disregard the stuff about AppDomain.CurrentDomain.UnhandledException. ---- ## Original report Looks like this is an issue impacting the community: https://www.reddit.com/r/Blazor/comments/vhrrl1/blazor_wasm_how_to_break_on_unhandled_exception/ Ideally we can hook into the `System.AppDomain.CurrentDomain.UnhandledException` as we do with WebView for WinForms / WPF. Repro: `Index.razor`: ```razor @code { public void ThrowException() { throw new Exception("throwing new ex"); } } ``` `Program.cs`: ```csharp System.AppDomain.CurrentDomain.UnhandledException += (sender, error) => { System.Console.WriteLine("!!! Encountered exception !!!"); }; ``` Expected: `!!! Encountered exception !!!` console output Actual: The exception breaks the world // stack trace dumps to console Kind of related: https://github.com/dotnet/maui/issues/5535
Author: TanayParikh
Assignees: -
Labels: `arch-wasm`, `untriaged`, `area-Debugger-mono`, `blazor-wasm`
Milestone: -
thaystg commented 2 years ago

This is not working because of two reasons: First of them is this issue that I have just opened that is completely unrelated to exceptions: https://github.com/dotnet/runtime/issues/71456

The second reason is that on Blazor code this exception is been caught. So we need to enable "all exceptions" in exception settings. image

Then it will pause correctly in the exception: image

radical commented 2 years ago

@javiercn Will this case get added to the manual tests?

TanayParikh commented 2 years ago

@javiercn Will this case get added to the manual tests?

I'll take care of it 😄

thaystg commented 2 years ago

To be clear, it will not pause in unhandled exception because the exception is caught by blazor code. So the user should check the "pause on all exceptions", then it will pause in the "unhandled" one.

image

TanayParikh commented 2 years ago

Created https://github.com/aspnet/AspNetCore-ManualTests/pull/1451 to add manual testing coverage in this area.

@javiercn @SteveSandersonMS should we perhaps be doing something different so that Blazor doesn't catch (or intentionally re-throw) the unhandled exception and so that JavaScript Exceptions -> Uncaught Exceptions would be sufficient?

Currently with JavaScript Exceptions -> All Exceptions, it's essentially a firehose of exceptions, and the user needs to immediately turn it off to actually progress with normal debugging.

jasonswearingen commented 2 years ago

Turning on all the Javascript exceptions works (All + Uncaught) Though it seems turning these on needs to occur after the app is all started, otherwise there are very many first-chance exceptions caught in the dotnet vm upon startup

So at least the method @thaystg described above is a mitigation for the time being.

SteveSandersonMS commented 2 years ago

should we perhaps be doing something different so that Blazor doesn't catch (or intentionally re-throw) the unhandled exception

Maybe. In WebAssemblyRenderer, we override HandleException and call Log.UnhandledExceptionRenderingComponent(..., exception, ...). Maybe we need to be rethrowing it instead.

The way the logging there works is a bit magical - the implementation comes from some kind of codegen based on a [LoggerMessage] attribute, so it's tough to see what it actually does internally. Maybe we should not be using that logic and should just rethrow instead.

javiercn commented 2 years ago

@jasonswearingen I would not say @thaystg is a mitigation, it is working as expected.

It is unfortunate that the runtime throws many exceptions during boot, however that is a separate problem.

For completeness, does it not work for you if you turn on the JavaScript Exceptions -> All Exceptions after the app has started?

@SteveSandersonMS I think we might just want to rethrow after we log the exception. That said, we would need to check if that changes the behavior, as I would expect that to crash the app, which if it currently does not, is a big breaking change. I vaguely recall this behavior being "by design", as we didn't care for the exceptions happening on the client (compared to server or now desktop). The reasoning I think it was something like, "an exception happened" but the app is likely to continue working afterwards, so we shouldn't actively prevent it and force a "refresh".

ghost commented 2 years ago

Thanks for contacting us.

We're moving this issue to the .NET 7 Planning milestone for future evaluation / consideration. We would like to keep this around to collect more feedback, which can help us with prioritizing this work. We will re-evaluate this issue, during our next planning meeting(s). If we later determine, that the issue has no community involvement, or it's very rare and low-impact issue, we will close it - so that the team can focus on more important and high impact issues. To learn more about what to expect next and how this issue will be handled you can read more about our triage process here.

ghost commented 2 years ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

mkArtakMSFT commented 2 years ago

After some further discussion, we think there is no further action to be taken here. We'll monitor this area in the future to see if we need to consider doing more here. But for now - closing this.

danroth27 commented 1 year ago

The user experience for debugging exceptions in Blazor WebAssembly apps isn't great. See https://twitter.com/eiriklb1/status/1716871699059388433 for an example of a user complaint about this. Could we maybe do something specifically during development to make the experience better?