Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Synchronization Not Working in Release Mode with Dotmim.Sync on MAUI App (AOT Compilation Error) #1268

Open
JustAnotherLars opened this issue Oct 30, 2024 · 1 comment

Comments

@JustAnotherLars
Copy link

JustAnotherLars commented Oct 30, 2024

Description:

I'm using Dotmim.Sync as a singleton service in a .NET MAUI app to handle data synchronization. The issue I’m experiencing is that synchronization works perfectly in Debug mode but fails in Release mode.
In Release mode, no synchronized objects are visible in the app, though the app itself doesn't crash. The following error message appears in the logs during synchronization attempts:

The error seems related to JIT compilation, which is restricted in AOT-only environments. I've tried enabling the Mono Interpreter for Release builds as a workaround:

<PropertyGroup Condition="$(TargetFramework.Contains('-ios')) and '$(Configuration)' == 'Release'"> <UseInterpreter>true</UseInterpreter> </PropertyGroup>
However, with this setting, the app fails to start entirely in Release mode.

Description:

I'm using Dotmim.Sync as a singleton service in a .NET MAUI app to handle data synchronization. The issue I’m experiencing is that synchronization works perfectly in Debug mode but fails in Release mode.

In Release mode, no synchronized objects are visible in the app, though the app itself doesn't crash. The following error message appears in the logs during synchronization attempts:

Dotmim.Sync.SyncException: [InternalEnsureScopeInfoAsync]..[InternalExistsScopeInfoAsync]..Attempting to JIT compile method '(wrapper dynamic-method) object object:Thunk1ret_Object_CallSite_Object_Object (System.Func`2<object[], object>,System.Runtime.CompilerServices.CallSite,object,object)' while running in aot-only mode. See https://docs.microsoft.com/xamarin/ios/internals/limitations for more information.

 ---> System.ExecutionEngineException: 

   at System.Delegate.CreateDelegate(Type , Object , MethodInfo , Boolean , Boolean )
   at System.Reflection.Emit.DynamicMethod.CreateDelegate(Type , Object )
   at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegateRefEmit(Type , Func`2 )
   at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegate(Type , Func`2 )
   at System.Linq.Expressions.Interpreter.LightLambda.MakeDelegate(Type )
   at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate(IStrongBox[] )
   at System.Linq.Expressions.Expression`1[[System.Func`4[[System.Runtime.CompilerServices.CallSite, System.Linq.Expressions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Compile()
   at System.Runtime.CompilerServices.CallSite`1[[System.Func`4[[System.Runtime.CompilerServices.CallSite, System.Linq.Expressions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].CreateCustomNoMatchDelegate(MethodInfo )
   at System.Runtime.CompilerServices.CallSite`1[[System.Func`4[[System.Runtime.CompilerServices.CallSite, System.Linq.Expressions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MakeUpdateDelegate()
   at System.Runtime.CompilerServices.CallSite`1[[System.Func`4[[System.Runtime.CompilerServices.CallSite, System.Linq.Expressions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetUpdateDelegate(Func`4& )
   at System.Runtime.CompilerServices.CallSite`1[[System.Func`4[[System.Runtime.CompilerServices.CallSite, System.Linq.Expressions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetUpdateDelegate()
   at System.Runtime.CompilerServices.CallSite`1[[System.Func`4[[System.Runtime.CompilerServices.CallSite, System.Linq.Expressions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]..ctor(CallSiteBinder )
   at System.Runtime.CompilerServices.CallSite`1[[System.Func`4[[System.Runtime.CompilerServices.CallSite, System.Linq.Expressions, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Object, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Create(CallSiteBinder binder)
   at Dotmim.Sync.SyncTypeConverter.TryConvertTo[String](Object value, CultureInfo provider)
   at Dotmim.Sync.SyncTypeConverter.TryConvertFromDbType(Object value, DbType typeOfT, CultureInfo provider)
   at Dotmim.Sync.BaseOrchestrator.InternalSetParameterValue(DbCommand command, String parameterName, Object value)
   at Dotmim.Sync.BaseOrchestrator.InternalExistsScopeInfoAsync(String scopeName, SyncContext context, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress`1 progress)
   at Dotmim.Sync.BaseOrchestrator.InternalExistsScopeInfoAsync(String scopeName, SyncContext context, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress`1 progress)
   Exception_EndOfInnerExceptionStack
   at Dotmim.Sync.LocalOrchestrator.InternalEnsureScopeInfoAsync(SyncContext context, DbConnection connection, DbTransaction transaction, CancellationToken cancellationToken, IProgress`1 progress)
   at Dotmim.Sync.SyncAgent.SynchronizeAsync(String scopeName, SyncSetup setup, SyncType syncType, SyncParameters parameters, CancellationToken cancellationToken, IProgress`1 progress)
   at DigitalMeasurementProtocol.MAUI.Services.SyncService.Sync()

The error seems related to JIT compilation, which is restricted in AOT-only environments. I've tried enabling the Mono Interpreter for Release builds as a workaround:

<PropertyGroup Condition="$(TargetFramework.Contains('-ios')) and '$(Configuration)' == 'Release'">
    <UseInterpreter>true</UseInterpreter>
</PropertyGroup>

However, with this setting, the app fails to start entirely in Release mode.

Steps to Reproduce:
Configure Dotmim.Sync as a singleton in a .NET MAUI app.
Run the synchronization in Debug mode - it works as expected.
Deploy the app in Release mode on an iOS device.
Observe the error in the log file.

Expected Behavior:
Synchronization should work in both Debug and Release modes without needing JIT compilation.

Actual Behavior:
In Debug mode, synchronization works as expected.
In Release mode, the synchronization fails due to the AOT restriction, and enabling the Mono Interpreter prevents the app from starting.

Version Information:
Dotmim.Sync.Core: 1.2.0
Dotmim.Sync.Sqlite: 1.2.0
Dotmim.Sync.Web.Client: 1.2.0
.NET MAUI: net8.0
Platform: iOS (Release mode)

Workarounds Attempted:
Enabled Mono Interpreter for Release builds (true), but the app fails to start.

Additional Context: Any advice on using Dotmim.Sync in AOT environments like iOS in Release mode, or if alternative configuration settings could resolve the AOT compilation issues, would be appreciated.

@JustAnotherLars
Copy link
Author

By the way, this function causes the error.

        public async Task Sync()
        {
            if(Connectivity.NetworkAccess != NetworkAccess.Internet)
            {
                _logger.LogInformation("No Internetconnection available. Sync aborted.");
                return;
            }
            try
            {
                var token = await _authorizationService.GetAuthenticationTokenAsync();
                var httpHandler = new HttpClientHandler
                {
                    AutomaticDecompression = System.Net.DecompressionMethods.GZip
                };
                HttpClient httpClient = new HttpClient(httpHandler);
                httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token.Token);
                httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new System.Net.Http.Headers.StringWithQualityHeaderValue("gzip"));
                var dbFile = Helpers.Constants.DbPath;
                if(dbFile is null)
                {
                    _logger.LogInformation("No database file found.");
                    return; 
                }
                _remoteOrchestrator = new WebRemoteOrchestrator(Constants.ServerAdr, client: httpClient);
                _syncProvider = new SqliteSyncProvider(dbFile);
                _syncAgent = new SyncAgent(_syncProvider, _remoteOrchestrator);
                var setup = new SyncSetup(new string[] { "User", "Project", "Measurement", "AbstractBaseEquipement", "Media", "AbstractBaseShape", "MeasurementLocation", "ProjectUser", "Line" });
                var result = await _syncAgent.SynchronizeAsync(setup);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "An error occured during synchronization.");
                throw;
            }
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant