dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.28k stars 1.76k forks source link

Back and forth Shell navigation end up crashing (Windows) #24858

Open elTRexx opened 2 months ago

elTRexx commented 2 months ago

Description

While troubleshooting my Shell navigation I end up create a very simple app to test it. Here is my repo .

I try to keep it a bare minimum that still crash the app (on windows at least, didn't try on android emulator)

Here is a video of me testing it ending a crash.

Steps to Reproduce

  1. Get my project on the repo listed above
  2. Run it on windows Machine
  3. click the button [Select item] to navigate to SelectPage
  4. click to the built in back button to navigate back to MainPage
  5. repeat 3. and 4. as long as you need to get eventually a crash

Link to public reproduction project repository

https://github.com/elTRexx/TestinMAUIPageNavigationPerf

Version with bug

8.0.82 SR8.2

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Windows

Affected platform versions

Windows SDK 10.1.22000.832

Did you find any workaround?

No

Relevant log output

> dotnet workload list

 dans .NET 8.0 !
---------------------
Version du kit SDK : 8.0.400

ID de la charge de travail installée      Version de manifeste      Source de l’installation
--------------------------------------------------------------------------------------------
maui-windows                              8.0.82/8.0.100            VS 17.11.35312.102
android                                   34.0.113/8.0.100          VS 17.11.35312.102
maccatalyst                               17.5.8030/8.0.100         VS 17.11.35312.102
ios                                       17.5.8030/8.0.100         VS 17.11.35312.102
OliveInto commented 2 months ago

This bug happens when naviagting in windows backward and forward very quickly. The offcial demo app 'eshop' will crash because of this bug too.

ninachen03 commented 2 months ago

This issue has been verified using Visual Studio 17.12.0 Preview 2.0(8.0.90 & 8.0.80 & 8.0.3). Can repro this issue at windows platform. image

elTRexx commented 2 months ago

So far after inquiring the issue, I found out that it may be related to the xaml code of the page we navigate in. Using a single and simple <Label/> will crash. I did receive help in my SO post by IVSoftware here. Using his code that doesn't crash and altering SelectPage XAML code, in the end I found out that using a simple <Label/> will crash it too, using only a 5 items Number will end up crashing also (could take time). But with 6 Number no crash (well at least up to ~1500 back forth loop cycles). But using those 6 number AND removing XAML <Border/> width constrains (resulting in a whole window width <Border/> display) end up crashing again then ... I'm not an MAUI code "arcanist", but digging in stack trace I found that the exception is thrown by ExceptionHelpers.ThrowExceptionForHR(((delegate* unmanaged[Stdcall]<IntPtr, IntPtr, int>)(*(IntPtr*)((nint)(*(IntPtr*)(void*)thisPtr) + (nint)27 * (nint)sizeof(delegate* unmanaged[Stdcall]<IntPtr, IntPtr, int>))))(thisPtr, MarshalInspectable<object>.GetAbi(value))); line in the IFrameMethod class. And if I'm correct this line will throw the exception if it's int parameter correspond to an error code. And this parameter result in the delegate call, witch is refereed in Frame class as _objRef_global__Microsoft_UI_Xaml_Controls_IFrame. Maybe that could help you?

OliveInto commented 2 months ago

So far after inquiring the issue, I found out that it may be related to the xaml code of the page we navigate in. Using a single and simple <Label/> will crash. I did receive help in my SO post by IVSoftware here. Using his code that doesn't crash and altering SelectPage XAML code, in the end I found out that using a simple <Label/> will crash it too, using only a 5 items Number will end up crashing also (could take time). But with 6 Number no crash (well at least up to ~1500 back forth loop cycles). But using those 6 number AND removing XAML <Border/> width constrains (resulting in a whole window width <Border/> display) end up crashing again then ... I'm not an MAUI code "arcanist", but digging in stack trace I found that the exception is thrown by ExceptionHelpers.ThrowExceptionForHR(((delegate* unmanaged[Stdcall]<IntPtr, IntPtr, int>)(*(IntPtr*)((nint)(*(IntPtr*)(void*)thisPtr) + (nint)27 * (nint)sizeof(delegate* unmanaged[Stdcall]<IntPtr, IntPtr, int>))))(thisPtr, MarshalInspectable<object>.GetAbi(value))); line in the IFrameMethod class. And if I'm correct this line will throw the exception if it's int parameter correspond to an error code. And this parameter result in the delegate call, witch is refereed in Frame class as _objRef_global__Microsoft_UI_Xaml_Controls_IFrame. Maybe that could help you?

I do not understand your testing process, but have you ever tried to wait few seconds before press back button? In my cases doing this will reduce the possibility of crashing. I guess there is something wrong with the page initializing process which takes long time, and pressing back button too early will forcibly break the process end up with the exception.

elTRexx commented 2 months ago

So far after inquiring the issue, I found out that it may be related to the xaml code of the page we navigate in. Using a single and simple <Label/> will crash. I did receive help in my SO post by IVSoftware here. Using his code that doesn't crash and altering SelectPage XAML code, in the end I found out that using a simple <Label/> will crash it too, using only a 5 items Number will end up crashing also (could take time). But with 6 Number no crash (well at least up to ~1500 back forth loop cycles). But using those 6 number AND removing XAML <Border/> width constrains (resulting in a whole window width <Border/> display) end up crashing again then ... I'm not an MAUI code "arcanist", but digging in stack trace I found that the exception is thrown by ExceptionHelpers.ThrowExceptionForHR(((delegate* unmanaged[Stdcall]<IntPtr, IntPtr, int>)(*(IntPtr*)((nint)(*(IntPtr*)(void*)thisPtr) + (nint)27 * (nint)sizeof(delegate* unmanaged[Stdcall]<IntPtr, IntPtr, int>))))(thisPtr, MarshalInspectable<object>.GetAbi(value))); line in the IFrameMethod class. And if I'm correct this line will throw the exception if it's int parameter correspond to an error code. And this parameter result in the delegate call, witch is refereed in Frame class as _objRef_global__Microsoft_UI_Xaml_Controls_IFrame. Maybe that could help you?

I do not understand your testing process, but have you ever tried to wait few seconds before press back button? In my cases doing this will reduce the possibility of crashing. I guess there is something wrong with the page initializing process which takes long time, and pressing back button too early will forcibly break the process end up with the exception.

Well my testing process used to be manual, like shown on the videos. But after receiving help from IVSoftware on my S.O. post, I used his testing approch to automate the back and forth navigation (calling GoToAsync() method on OnNavigatedTo() event handler after an await Task.Delay(TimeSpan.FromSeconds(1)). I did notice, but without any certainty, that reducing time delay (e.g. to 250 ms) trend to raise the crash / exception sooner. But it is just an observation guess, nothing really measured. Anyway, even if this bug is hardly to reproduce in real life scenario due to unliklyness of those repeated back and forth navigation doesn't eliminate the fact that there is a bug.

elTRexx commented 2 months ago

I have used this IVSoftware simplified repo, and modified it in order to distinguish exception originating from MainPage navigation from those originating from ChildPageA.

Using his deduction that registering ChildPageA as a singleton in built-in MAUI DI container is the cause of the exception while I found that XAML code of the child page could be in relation to the exception, I found out on 2 long test (2 * 10000 back and forth calls) that with singleton registration of ChildPageA there is exception thrown both from MainPage to ChildPageA navigation and in the other way around (from ChildPageA to MainPage).

Without singleton registration (removing the AddSingleton() calll in MauiProgram.cs) then only the navigation from ChildPagea to MainPage are thrown. The exceptions are thrown in the same order of magnitude (around 1,4% of navigation GoToAsync() calls). I will have to test if modifying ChildPageA.xaml XAML code wioll remove the ChildPageA to MainPage exception.

elTRexx commented 2 months ago

With XAML code displaying what I displayed in my project (a grid of numbers), tested with 6 and 5 numbers. I expected no crash with 6 and some crashes with 5. But I ended up with 1 early crash with 6 numbers coded in XAML at ~300 cycles out of 10 000, and only 2 early crashes with 5 numbers coded in XAML at 25 and 49 cycles out of 10 000. So kinda no crash without singleton AND with more "complex" XAML code. I doubt XAML code is a primary culprit here, more a side effect thing i guess.

elTRexx commented 2 months ago

Just to amend my previous statement, Using AddSingleton<ViewPage>() is required to have better performance in navigation, because without that it recreate and rebind the data of the so said ViewPage. But then we hit the bug of NavigationFailed was unhandled quite often in real life use case scenario, even without no that fast back and forth navigation. So either this bug can be resolved or maybe you know another way to get a performant page navigation without registrering the ViewPage as singleton ?

OliveInto commented 2 months ago

Just to amend my previous statement, Using AddSingleton<ViewPage>() is required to have better performance in navigation, because without that it recreate and rebind the data of the so said ViewPage. But then we hit the bug of NavigationFailed was unhandled quite often in real life use case scenario, even without no that fast back and forth navigation. So either this bug can be resolved or maybe you know another way to get a performant page navigation without registrering the ViewPage as singleton ?

I found this bug monthes ago, but as a none-native speaker, it is hard for me to discripe it as clearly as you can, therefore I just wait for someone to report it. And you can see other issues, there are so many bugs remain unsolved for years and many of them I have met in during development, hopefully this will be solved in the furture, but I think the possibility is rare.