dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.15k stars 4.71k forks source link

Xamarin.IOs Operation is not supported on this platform #35988

Closed DerGary closed 3 years ago

DerGary commented 4 years ago

Describe the bug

I can't really describe why the bug is occuring Because I don't understand where in the code exactly it occurs. But I try my best. So I have a Xamarin.IOs app with different Pages. When I navigate to a page that creates a couple of ViewModels (that are using Dependency Injection) then navigate back and then navigate to this page again, then an exception is raised in an unobserved task that seems to be outside my own code. I can't debug to the exception only after it happened the UnobservedException call back is triggered and there i could log the exception. It looks like this:

[24.02.20 - 08:24:13] Exception - AppDelegate.cs:UnobservedExceptionOccured:44
Exception from System.Threading.Tasks.Task`1[System.Func`2[Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope,System.Object]]

[24.02.20 - 08:24:13] Exception: System.AggregateException - AppDelegate.cs:UnobservedExceptionOccured:46
System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. (Operation is not supported on this platform.) ---> System.PlatformNotSupportedException: Operation is not supported on this platform.
  at System.Reflection.Emit.DynamicMethod..ctor (System.String name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] parameterTypes, System.Type owner, System.Boolean skipVisibility) [0x00006] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/corlib/System.Reflection.Emit/DynamicMethod.notsupported.cs:74 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ILEmitResolverBuilder.BuildTypeNoCache (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite callSite) [0x00038] in <508b355622de4308a7332aefb4667c94>:0 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ILEmitResolverBuilder.BuildType (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite callSite) [0x00055] in <508b355622de4308a7332aefb4667c94>:0 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ILEmitResolverBuilder.Build (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite callSite) [0x00039] in <508b355622de4308a7332aefb4667c94>:0 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CompiledServiceProviderEngine.RealizeService (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite callSite) [0x00006] in <508b355622de4308a7332aefb4667c94>:0 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>n__0 (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite callSite) [0x00000] in <508b355622de4308a7332aefb4667c94>:0 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine+<>c__DisplayClass1_0.<RealizeService>b__1 () [0x00000] in <508b355622de4308a7332aefb4667c94>:0 
  at System.Threading.Tasks.Task`1[TResult].InnerInvoke () [0x0000f] in <7df0b59b3ac34c319d58e821ad54104a>:0 
  at System.Threading.Tasks.Task.Execute () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corert/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs:2319 
   --- End of inner exception stack trace ---
---> (Inner Exception #0) System.PlatformNotSupportedException: Operation is not supported on this platform.
  at System.Reflection.Emit.DynamicMethod..ctor (System.String name, System.Reflection.MethodAttributes attributes, System.Reflection.CallingConventions callingConvention, System.Type returnType, System.Type[] parameterTypes, System.Type owner, System.Boolean skipVisibility) [0x00006] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/corlib/System.Reflection.Emit/DynamicMethod.notsupported.cs:74 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ILEmitResolverBuilder.BuildTypeNoCache (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite callSite) [0x00038] in <508b355622de4308a7332aefb4667c94>:0 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ILEmitResolverBuilder.BuildType (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite callSite) [0x00055] in <508b355622de4308a7332aefb4667c94>:0 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.ILEmitResolverBuilder.Build (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite callSite) [0x00039] in <508b355622de4308a7332aefb4667c94>:0 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.CompiledServiceProviderEngine.RealizeService (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite callSite) [0x00006] in <508b355622de4308a7332aefb4667c94>:0 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>n__0 (Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceCallSite callSite) [0x00000] in <508b355622de4308a7332aefb4667c94>:0 
  at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine+<>c__DisplayClass1_0.<RealizeService>b__1 () [0x00000] in <508b355622de4308a7332aefb4667c94>:0 
  at System.Threading.Tasks.Task`1[TResult].InnerInvoke () [0x0000f] in <7df0b59b3ac34c319d58e821ad54104a>:0 
  at System.Threading.Tasks.Task.Execute () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corert/src/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs:2319 <---

To Reproduce

Steps to reproduce the behavior:

  1. Using version '3.1.x' of package 'Microsoft.Extensions.DependencyInjection'
  2. Using version '4.2.0.910310' of package 'Xamarin.Forms'
  3. I don't know how to reproduce it exactly because I can't figure out where in the code the exception is triggered.

Expected behavior

No Exception is thrown (it works on 3.0.x)

Kation commented 4 years ago

I'have the same exception.

purplerockcvd commented 4 years ago

I also have this. It's a major problem for us.

tranb3r commented 4 years ago

I have the same exception. Everything is fine when using 3.0.x.

tranb3r commented 4 years ago

It seems like xamarin.ios is picking the netstandard2.1 version of microsoft.extensions.dependencyinjection 3.1.x. When using netstandard2.1, the IL_EMIT constant is set and the DI code switches to ILEmitResolverBuilder instead of ExpressionResolverBuilder. ILEmit is not supported on ios, this is why the exception is raised.

3.0.x does not support netstandard2.1, and when the targetFramework is netstandard2.0, the ILEmitBackend is not used. This is why everything is ok when using 3.0.x.

Maybe IL_EMIT should not be set for netstandard2.1, just like for netstandard2.0 ?

analogrelay commented 4 years ago

Triage: It should be possible to detect this with the runtime capability API and have DI switch from IL Emit mode to Reflection when IL Emit is not available. Marking for transfer to runtime for 5.0 consideration.

Dotnet-GitSync-Bot commented 4 years ago

I couldn't figure out the best area label to add to this issue. Please help me learn by adding exactly one area label.

maryamariyan commented 4 years ago

The reason we are hitting in Xamarin is because from

https://github.com/dotnet/runtime/blob/855e2961ba70d3ed8b094d230aaf655adac2b76e/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceCollectionContainerBuilderExtensions.cs#L63-L75

we are hitting line 64.

IsDynamicCodeCompiled is only available in netcoreapp. When Xamarin moves to .NET Core runtime, this issue would get fixed.

tranb3r commented 3 years ago

The issue seems to be gone when using version 3.1.11 of 'Microsoft.Extensions.DependencyInjection'

davidfowl commented 3 years ago

Is this issue still relevant?

tranb3r commented 3 years ago

The issue is gone, but if we don't know what was causing it and what has changed that fixed it, it'll come back. Also, there should be some kind of unit test, to guarantee that xamarin.ios will continue to be properly supported in the future.

eerhardt commented 3 years ago

This issue is fixed if you use the latest bits.

Using version '4.2.0.910310' of package 'Xamarin.Forms'

Older versions of Xamarin forms use the netstandard2.0 asset from Microsoft.Extensions.DependencyInjection. When using the netstandard2.1 version of the library:

https://github.com/dotnet/runtime/blob/24900f8333bd97ebb9b5837bbec10c28f02598d8/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceCollectionContainerBuilderExtensions.cs#L63-L74

it checks if (RuntimeFeature.IsDynamicCodeCompiled). If ILEmit is not supported on the platform (which it shouldn't be on iOS as far as I know), RuntimeFeature.IsDynamicCodeCompiled will return false. Which means we will never try to use ILEmit.

Closing. If you see this again with the latest versions, feel free to re-open.