ExecutionEngineException "Attempting to JIT compile method" when assigning delegate class

Hi all,

I recently encountered the following bug in our App that is making our application crash:

System.ExecutionEngineException: Attempting to JIT compile method 'My.Binding.Project.SdkInterface:set_WeakDelegate (Foundation.NSObject)' while running in aot-only mode. See https://developer.xamarin.com/guides/ios/advanced_topics/limitations/ for more information.

The exception originates from within an iOS binding-project that we've included in our App as a NuGet-package. Within that project, we bind an SDK that discloses an "interface" (binding), which exposes a singleton of itself as a static SharedInstance-property. It is when assigning the Delegate-property of this shared instance from within a wrapper class inside the binding-project that the exception actually occurs.

The question, of course, is how to prevent this exception from occurring. A bug report has been filed here, with the problem seeming rather similar to this forum post.

Example code

The code of our binding-project can be abstracted as such:

ApiDefinitions.cs

namespace My.Bindings.Project
{
  [Internal]
  [BaseType(typeof(NSObject))]
  interface SdkInterface
  {
    [Static]
    [Export("sharedInstance")]
    SdkInterface SharedInstance { get; }
  }

  [Internal]
  [Protocol, Model]
  [BaseType(typeof(NSObject))]
  interface Delegate
  {
    [Abstract]
    [Export("sdk:customEvent:")]
    void CustomEvent(SdkInterface sdkInterface, NSDictionary values);
  }
}

SdkEventListener.cs

namespace My.Bindings.Project
{
  internal class SdkEventListener : Delegate
  {
    public event EventHandler<CustomEventArgs> Event;

    public override void CustomEvent(SdkInterface sdkInterface, NSDictionary values)
      => this.Event?.Invoke(this, new CustomEventArgs(values));
  }
}

SdkManager.cs

namespace My.Bindings.Project
{
  public class SdkManager : SdkInterface
  {
    public event EventHandler<CustomEventArgs> Event;

    private SdkInterface Sdk { get; }

    private SdkEventListener Listener => (SdkEventListener) this.Sdk.Delegate;

    public SdkManager()
    {
      this.Sdk = SdkInterface.SharedInstance;
      this.Sdk.Delegate = new SdkEventListener();
      this.Listener.Event += this.OnSdkEvent;
    }

    protected virtual void OnSdkEvent(object sender, CustomEventArgs e)
      => this.Event?.Invoke(this, e);
  }
}

Development environment

We mainly develop our App in Visual Studio 2015 Update 3, but use a Mac build-agent to compile our iOS-project. The Mac-agent runs on a machine that has both Xamarin Studio and Visual Studio 2017 for Mac installed against Xamarin.iOS-version 10.10.0.36 and Xamarin.Mac-version 3.4.0.36. Our project's linker behaviour is set to "Link Framework SDKs Only".

What has been checked

  1. The existing build of our NuGet (i.e. the binding-project) with an older version of the SDK works without issues.
  2. Building a new NuGet-package with a newer version of the SDK does not resolve the issue.
  3. Rebuilding the same NuGet-package as in nr. 1 results in a package that now also throws the exception.
  4. The bug has existed since at least June 7th, as a previous build of our App from that date also already includes the bug.
  5. Excluded a recent upgrade of the Xamarin.Forms used in our App from 2.3.4.231 to 2.3.4.247 as cause of the exception.
  6. The frequently offered work-around of setting the App-project's linker behaviour to "Don't Link" doesn't work for me, as Xamarin.iOS requires the iOS 10.3 SDK, whereas we've currently only got 10.2 available (due to Xcode dependencies). Attempting to compile the code anyway results in the following compile-time error message:
    This version of Xamarin.iOS requires the iOS 10.3 SDK (shipped with Xcode 8.3). Either upgrade Xcode to get the required header files or set the managed linker behaviour to Link Framework SDKs Only (to try to avoid the new APIs).
  7. The alternative recurring solution of setting the App-project's linker behaviour to "Link All" results in an unhandled exception, even prior to the point in the code where the ExecutionEngineException would otherwise have been thrown.
  8. Setting the Foundation.PreserveAttribute on the delegate class (SdkEventListener above) as I've seen suggested on this forum too, also does not resolve the issue.

Answers

  • prashantvcprashantvc USXamarin Team Xamurai

    @AlexanderMelchers Thank you for the detailed the post.

    Looks like you have already tried all the recommended fix. Is it possible to share test case reproducing this issue?
    If it's confidential please send me a direct message

  • AlexanderMelchersAlexanderMelchers NLMember ✭✭

    @prashantvc Thanks for your quick response to my post! Unfortunately, however, I'm not allowed to disclose the code, or even share it privately. Luckily, the issue is not pressing at the moment, though, as we can survive with an older version of the SDK, but would need a solution by this time next month.

  • prashantvcprashantvc USXamarin Team Xamurai

    Unfortunately, however, I'm not allowed to disclose the code, or even share it privately.

    I understand, would it be possible to share the complete crash log and verbose build log? You can find the instructions here. It will help us to troubleshoot the issue.

    You can email ([email protected]) me directly if you do not want to share them on the forum

  • AlexanderMelchersAlexanderMelchers NLMember ✭✭

    Tried the suggestion of using code optimization made by Alex Soto in the bug report, but only had limited success doing so. That is to say, when using code optimization on the NuGet-package, and running the final project from a Mac (either from within Xamarin Studio or Visual Studio), the application now starts up and runs without crashes, but unfortunately also no longer offers the functionality disclosed by the SDK wrapped inside the NuGet-package/binding-project.

    My impression as to the cause underlying the latter observation is that the events I expect to receive from the SDK originate with the delegate class which assignment used to cause the ExecutionEngineException. Though code optimization seems to suppress this exception, it still does not seems to do a proper assignment, as otherwise I would have expected the events to have been propagated onto the final project.

  • AlexanderMelchersAlexanderMelchers NLMember ✭✭

    @prashantvc I sent you a PM with the logs :smile:

Sign In or Register to comment.