@brendanzagaeski has diagnosed an issue wherein object references are collected when we think they shouldn't be.
Consider the following generator-emitted binding code:
publicunsafeboolHideSoftInputFromWindow(Android.OS.IBinder?windowToken,[global::Android.Runtime.GeneratedEnum]Android.Views.InputMethods.HideSoftInputFlagsflags){conststring__id="hideSoftInputFromWindow.(Landroid/os/IBinder;I)Z";try{JniArgumentValue*__args=stackallocJniArgumentValue[2];/* 1 */__args[0]=newJniArgumentValue((windowToken==null)?IntPtr.Zero:((global::Java.Lang.Object)windowToken).Handle);/* 2 */__args[1]=newJniArgumentValue((int)flags);/* 3 */var__rm=_members.InstanceMethods.InvokeAbstractBooleanMethod(__id,this,__args);return__rm;}finally{}}Depending on "various factors", it is possible that Mono's GC will decide that windowToken -- used on line (1) -- is eligible for collection on line (2), when it must be kept alive until after line (3) completes execution.
If windowTokenisn't kept alive, then it could be finalized before/during the InvokeAbstractBooleanMethod() invocation, which could invalidate/change windowToken.Handle, and cause lots of head scratching, confusion, and app crashes.
The fix? We need to emit a GC.KeepAlive() for all reference types until after the Invoke* invocation has completed:
publicunsafeboolHideSoftInputFromWindow(Android.OS.IBinder?windowToken,[global::Android.Runtime.GeneratedEnum]Android.Views.InputMethods.HideSoftInputFlagsflags){conststring__id="hideSoftInputFromWindow.(Landroid/os/IBinder;I)Z";try{JniArgumentValue*__args=stackallocJniArgumentValue[2];__args[0]=newJniArgumentValue((windowToken==null)?IntPtr.Zero:((global::Java.Lang.Object)windowToken).Handle);__args[1]=newJniArgumentValue((int)flags);var__rm=_members.InstanceMethods.InvokeAbstractBooleanMethod(__id,this,__args);/* FIX */global::System.GC.KeepAlive(windowToken);return__rm;}finally{}}
@brendanzagaeski has diagnosed an issue wherein object references are collected when we think they shouldn't be.
Consider the following
generator-emitted binding code:Depending on "various factors", it is possible that Mono's GC will decide that
windowToken-- used on line (1) -- is eligible for collection on line (2), when it must be kept alive until after line (3) completes execution.If
windowTokenisn't kept alive, then it could be finalized before/during theInvokeAbstractBooleanMethod()invocation, which could invalidate/changewindowToken.Handle, and cause lots of head scratching, confusion, and app crashes.The fix? We need to emit a
GC.KeepAlive()for all reference types until after theInvoke*invocation has completed: