runtime: [BUG] ExecutionEngineException when deserializing generic [DataContract] on iOS (Realease Build, only through app store)

Description

Exception thrown when deserializing datacontract on iOS. The problem only occurs when the app has been deployed through AppStore/TestFlight.

System.ExecutionEngineException: Attempting to JIT compile method '(wrapper delegate-invoke) void <Module>:invoke_callvirt_void_Element_string (AnleggsSentralen.Checklist.Element,string)' while running in aot-only mode. See https://docs.microsoft.com/xamarin/ios/internals/limitations for more information.

   at System.Runtime.Serialization.FastInvokerBuilder.<>c__DisplayClass12_1`2[[AnleggsSentralen.Checklist.Element, AnleggsSentralen.Checklist, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].<CreateSetterInternal>b__1(Object& , Object )
   at System.Runtime.Serialization.ReflectionReader.ReflectionSetMemberValue(Object& , Object , DataMember )
   at System.Runtime.Serialization.ReflectionReader.ReflectionReadMember(XmlReaderDelegator , XmlObjectSerializerReadContext , ClassDataContract , Object& , Int32 , DataMember[] )
   at System.Runtime.Serialization.ReflectionXmlReader.ReflectionReadMembers(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] , ClassDataContract , Object& )
   at System.Runtime.Serialization.ReflectionReader.ReflectionReadClass(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] , ClassDataContract )
   at System.Runtime.Serialization.ReflectionXmlClassReader.ReflectionReadClass(XmlReaderDelegator , XmlObjectSerializerReadContext , XmlDictionaryString[] , XmlDictionaryString[] )
   at System.Runtime.Serialization.DataContracts.ClassDataContract.ReadXmlValue(XmlReaderDelegator , XmlObjectSerializerReadContext )
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.ReadDataContractValue(DataContract , XmlReaderDelegator )
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator reader, String name, String ns, Type declaredType, DataContract& dataContract)
   at System.Runtime.Serialization.XmlObjectSerializerReadContext.InternalDeserialize(XmlReaderDelegator xmlReader, Type declaredType, DataContract dataContract, String name, String ns)
   at System.Runtime.Serialization.DataContractSerializer.InternalReadObject(XmlReaderDelegator , Boolean , DataContractResolver )
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObjectHandleExceptions(XmlReaderDelegator , Boolean , DataContractResolver )
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(XmlDictionaryReader )
   at System.Runtime.Serialization.XmlObjectSerializer.ReadObject(Stream )
   at AnleggsSentralen.Checklist.Checklist.Load(Stream stream)
   at AnleggsSentralen.Checklist.Checklist.LoadAsync(Stream stream)
   at AnleggsSentralen.Client.Services.ChecklistService.GetChecklistTemplateAsync(Int32 id)
   at AnleggsSentralen.App.Services.DataLake.<GetDraftAsync>d__27`1[[AnleggsSentralen.Checklist.Checklist, AnleggsSentralen.Checklist, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]].MoveNext()
   at AnleggsSentralen.App.ViewModels.ChecklistViewModel.LoadChecklistFromTemplateAsync()
   at Herreruud.Framework.Mvvm.AsyncHelper.TraceExceptions(Func`1 factory, String method, String path)

Reproduction Steps

Deserialize generic datacontract on iOS in release build through AppStore/TestFlight. I am unable to reproduce locally.

Expected behavior

The datacontract should deserialize

Actual behavior

ExecutionEngine is thrown

Regression?

No response

Known Workarounds

No response

Configuration

  • net7.0-ios
  • ios
  • AppStore
  • Arm64

Other information

In the file “src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/AccessorBuilder.cs”, I can find the following code, that I suspect is the problem:

// If either of the arguments to MakeGenericMethod is a valuetype, this is going to cause JITting.
 // Only JIT if dynamic code is supported.
 if (RuntimeFeature.IsDynamicCodeSupported || (!declaringType.IsValueType && !propertyType.IsValueType))
    {
        #pragma warning disable IL3050 // AOT compiling should recognize that this call is gated by RuntimeFeature.IsDynamicCodeSupported.
       var createSetterGeneric = s_createSetterInternal.MakeGenericMethod(propInfo.DeclaringType!, propInfo.PropertyType).CreateDelegate<Func<PropertyInfo, Setter>>();
        #pragma warning restore IL3050 // Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.
            return createSetterGeneric(propInfo);
        }
        else
        {
            return (ref object obj, object? val) =>
            {
                propInfo.SetValue(obj, val);
            };
        }

Also, The method itself is annotated with:

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod",
            Justification = "The call to MakeGenericMethod is safe due to the fact that FastInvokerBuilder.CreateSetterInternal<T, T1> is not annotated.")]
        public static Setter CreateSetter(MemberInfo memberInfo)

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 39 (22 by maintainers)

Most upvoted comments

Also, why does this not occur for debug builds? I have a debug build in production in the AppStore right now (unfortunatly).

I believe interpreter should be on by default in debug builds, which is why it’s working for you. I suspect that property is somehow not set in your release project. In interpreter mode, RuntimeFeature.IsDynamicCodeSupported becomes true.

@LeVladIonescu Sorry, I’ve been away. The setting has no effect (that I can tell) on my main project. I haven’t tried it with the demo project.

I still think the following snippet reveals th eproblem, though:

if (RuntimeFeature.IsDynamicCodeSupported || (!declaringType.IsValueType && !propertyType.IsValueType))

The correct way of fixning it might be figuring out why the strings in question causes JIT - given that strings are not value types, but simply removing the second part of the if should probably fix it as well.

Also, why does this not occur for debug builds? I have a debug build in production in the AppStore right now (unfortunatly).

@LeVladIonescu I see that the above dump didn’t include SDK version: 7.0.100