xamarin / XamarinCommunityToolkit

The Xamarin Community Toolkit is a collection of Animations, Behaviors, Converters, and Effects for mobile development with Xamarin.Forms. It simplifies and demonstrates common developer tasks building iOS, Android, and UWP apps with Xamarin.Forms.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Bug] Popup causes app to crash after changing app theme

mfeingol opened this issue · comments

Description

I'm seeing this in crash reporting, so I don't know 100% what's going on. What I believe is happening is that a Popup has been opened and then closed, and then the app's theme changed from dark to light or vice-versa. The Popup receives that event, presumably because it has a weak reference registration dangling somewhere. When it attempts to process it, the renderer has already been disposed, so the result is an unhandled ObjectDisposedException.

I imagine a repro should be possible, but it wouldn't be 100% since there is presumably a race between the user and the GC. Presumably this can be solved via code inspection.

Stack Trace

System.ObjectDisposedException: Cannot access a disposed object. Object name: 'Xamarin.CommunityToolkit.UI.Views.PopupRenderer'

niPeerMembers.AssertSelf (Java.Interop.IJavaPeerable self)
JniPeerMembers+JniInstanceMethods.InvokeVirtualObjectMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters)
Dialog.get_Window ()
PopupRenderer.SetColor (Xamarin.CommunityToolkit.UI.Views.BasePopup& basePopup)
PopupRenderer.OnElementPropertyChanged (System.Object sender, System.ComponentModel.PropertyChangedEventArgs args)
(wrapper delegate-invoke) <Module>.invoke_void_object_PropertyChangedEventArgs(object,System.ComponentModel.PropertyChangedEventArgs)
BindableObject.OnPropertyChanged (System.String propertyName)
Element.OnPropertyChanged (System.String propertyName)
BindableObject.SetValueActual (Xamarin.Forms.BindableProperty property, Xamarin.Forms.BindableObject+BindablePropertyContext context, System.Object value, System.Boolean currentlyApplying, Xamarin.Forms.Internals.SetValueFlags attributes, System.Boolean silent)
BindableObject.SetValueCore (Xamarin.Forms.BindableProperty property, System.Object value, Xamarin.Forms.Internals.SetValueFlags attributes, Xamarin.Forms.BindableObject+SetValuePrivateFlags privateAttributes)
AppThemeBinding.ApplyCore ()
<.ctor>b__2_1 ()
Thread+RunnableImplementor.Run ()
IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this)
JNINativeWrapper.Wrap_JniMarshal_PP_V (_JniMarshal_PP_V callback, System.IntPtr jnienv, System.IntPtr klazz)

Link to Reproduction Sample

N/A

Steps to Reproduce

See above.

Expected Behavior

Popup should handle this case and not throw an ODE.

Actual Behavior

It throws.

Basic Information

  • Version with issue: 2.0.5
  • Last known good version: N/A
  • IDE: VS 2022
  • Platform Target Frameworks:
    • Android: 13

Workaround

None.

Anyone?

@mfeingol a sample project would be great here... On XF the Views are aggressively disposed of, so (just a shoot in the dark) if the popup is dismissed it will be disposed already, and if anything else tries to access it will cause this exception

Unfortunately I can't reproduce this in the debugger. I've only seen it in crash reports when I submit my app to the store.

Based on the stack trace, a first possible approach to a fix might be to check for this.isDisposed in OnElementPropertyChanged prior to calling SetColor.

A gentle ping on this: would it be possible to release a new version with that check implemented?

What you could do, in meanwhile, is to not reuse the same popup, always create a new instance of it.

I am. If you look at the stack trace above, the problem isn't popup instance reuse, but theme changes resulting in OnElementPropertyChanged being called on a disposed Popup.

Can you provide a sample that reproduces the issue? That's new

I cannot. Like I said, the only time I've seen this is in stack traces on AppCenter crash reports, which arrive after I submit an app to the Google Play Store.

My app opens a popup on startup, so my guess is the popup is closed and then Google test very quickly goes to the settings page and changes the first setting, which happens to be an app theme radio button.

you can't reproduce it even on a release build? Or if you copy all the release configurations to your debug configuration and run with the debugger attached? Even with the stack trace is hard to see what action does the crash

I've tried, but I haven't been able to reproduce it. My guess is the GC runs fast enough that the Popup is gone. The theme changed event in the stack trace is probably driven by a weak reference, right?

@pictos: I'm still seeing this when publishing to the Play Store. Any chance you could try applying the potential solution I mentioned above? I don't think it would hurt anything. Thanks!

image

@pictos: I'm still seeing this when publishing to the Play Store. Any chance you could try applying the potential solution I mentioned above? I don't think it would hurt anything. Thanks!

image

Would you be able to try and apply your suggestion locally and see if it solves the issue, if so then we could include it in this repository. I am not keen on on trying some changes that we can't verify whether they fix the issue or not.

I'm not able to reproduce the issue locally, so I wouldn't be able to verify a solution that way. Are you suggesting I compile a custom version of the toolkit and submit to the store?

I'm not able to reproduce the issue locally, so I wouldn't be able to verify a solution that way. Are you suggesting I compile a custom version of the toolkit and submit to the store?

Yes exactly that. If you fork the repository, make your changes and compile it. You can then just reference that dll rather than the NuGet package and ship the app. If the change works then you are in a perfect position to open a PR with the changes on your fork.

Alternatively you might be able to just include the Popup code in your codebase if that is your preferred option. I don't know if we are using any internals from Xamarin.Forms for the Popup though

@bijington: I managed to extract Popup out of XCT and build a store release with this change applied:

                protected virtual void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
		{
+			if (isDisposed) return;

After shipping the new release to the store, the unhandled ObjectDisposedException was no longer reported in the Popup renderer. So I think this change is effective at solving the problem.

@mfeingol that is great to hear! Out of interest how long was the application running for with this new release? Basically how confident are you that the issue is resolved given it was difficult to reproduce in the first place?

Repro was pretty regular with a Play Store submission, so I'm confident. Outside of that it's been impossible to repro.

OK great! Well let's get this fix in and merged ready for the next release :). Are you comfortable opening a PR for it? Or would you prefer me to do it?

Thanks. I submitted #1968