realm-dotnet: Using Realm with a SynchronizationContext implementation that is not single-thread-affine
Crash at Realms.SynchronizationContextEventLoopSignal/EventLoop
Goal
I have a complex async/await/Reactive flow which uses multiple Realm instances using the same RealmConfiguration
and also has a custom SynchronizationContext
involved that is crashing almost 100% of the time. The Realm 0.80.0 version of the App runs fine.
I repo’d this “random” issue using xUnit for Devices
/ Xunit.Sdk.AsyncTestSyncContext
and Realm 0.81.0 as it produces a similar crash and stack trace. You will a see repeating xUnit [Theory]
in the unit test to ensure that it does crash. It almost always crashes on the first execution, but sometimes it might work 2,3 times before crashing… as the crash is not 100% deterministic.
Expected Results
No crash due to custom SynchronizationContext
Actual Results
libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.
Realm0810SynchronizationContext[24731:19379897] critical: Stacktrace:
critical: at <unknown> <0xffffffff>
critical: at (wrapper managed-to-native) object.wrapper_native_0x10f019150 (intptr) <IL 0x00009, 0x000dd>
critical: at Realms.SynchronizationContextEventLoopSignal/EventLoop/<Post>c__AnonStorey0.<>m__0 (object) <IL 0x0001e, 0x000a5>
critical: at Xunit.Sdk.AsyncTestSyncContext/<>c__DisplayClass7_0.<Post>b__1 (object) <IL 0x0000c, 0x00082>
critical: at Xunit.Sdk.MaxConcurrencySyncContext.RunOnSyncContext (System.Threading.SendOrPostCallback,object) <IL 0x0000d, 0x000c4>
critical: at Xunit.Sdk.MaxConcurrencySyncContext/<>c__DisplayClass11_0.<WorkerThreadProc>b__0 (object) <IL 0x0001c, 0x000f3>
critical: at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) [0x0008d] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:957
critical: at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) [0x00000] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:904
critical: at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object) [0x00031] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:893
critical: at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object_object_object (object,intptr,intptr,intptr) <IL 0x00065, 0x00352>
critical: at <unknown> <0xffffffff>
critical: at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&) <IL 0x00016, 0x00131>
critical: at System.Reflection.MonoMethod.Invoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) [0x00038] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/corlib/System.Reflection/MonoMethod.cs:305
critical: at System.Reflection.MethodBase.Invoke (object,object[]) [0x00000] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/reflection/methodbase.cs:229
critical: at Microsoft.Scripting.Interpreter.MethodInfoCallInstruction.InvokeWorker (object[]) [0x00010] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.cs:261
critical: at Microsoft.Scripting.Interpreter.MethodInfoCallInstruction.Invoke (object[]) [0x00000] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.cs:239
critical: at Microsoft.Scripting.Interpreter.MethodInfoCallInstruction.Run (Microsoft.Scripting.Interpreter.InterpretedFrame) [0x0003b] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Instructions/CallInstruction.cs:289
critical: at Microsoft.Scripting.Interpreter.Interpreter.Run (Microsoft.Scripting.Interpreter.InterpretedFrame) [0x0001b] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/Interpreter.cs:126
critical: at Microsoft.Scripting.Interpreter.LightLambda.RunVoid2<T0_REF, T1_REF> (T0_REF,T1_REF) [0x0002a] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/dlr/Runtime/Microsoft.Dynamic/Interpreter/LightLambda.Generated.cs:117
critical: at Xunit.Sdk.ExecutionContextHelper.Run (object,System.Action`1<object>) <IL 0x00011, 0x000f3>
critical: at Xunit.Sdk.MaxConcurrencySyncContext.WorkerThreadProc () <IL 0x0007c, 0x00450>
critical: at Xunit.Sdk.XunitWorkerThread/<>c.<QueueUserWorkItem>b__5_0 (object) <IL 0x0000d, 0x000d1>
critical: at System.Threading.Tasks.Task.InnerInvoke () [0x0002b] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs:2885
critical: at System.Threading.Tasks.Task.Execute () [0x00016] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs:2502
critical: at System.Threading.Tasks.Task.ExecutionContextCallback (object) [0x00007] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs:2865
critical: at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) [0x0008d] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:957
critical: at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) [0x00000] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:904
critical: at System.Threading.Tasks.Task.ExecuteWithThreadLocal (System.Threading.Tasks.Task&) [0x0005f] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs:2827
critical: at System.Threading.Tasks.Task.ExecuteEntry (bool) [0x0006f] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/Tasks/Task.cs:2760
critical: at System.Threading.Tasks.ThreadPoolTaskScheduler.LongRunningThreadWork (object) [0x00007] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/Tasks/ThreadPoolTaskScheduler.cs:47
critical: at System.Threading.ThreadHelper.ThreadStart_Context (object) [0x0002c] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/thread.cs:72
critical: at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) [0x0008d] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:957
critical: at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) [0x00000] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:904
critical: at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object) [0x00031] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:893
critical: at System.Threading.ThreadHelper.ThreadStart (object) [0x00012] in /Users/builder/data/lanes/3985/b4a43820/source/xamarin-macios/_ios-build/Library/Frameworks/Xamarin.iOS.framework/Versions/git/src/mono/mcs/class/referencesource/mscorlib/system/threading/thread.cs:87
critical: at (wrapper runtime-invoke) <Module>.runtime_invoke_void__this___object (object,intptr,intptr,intptr) <IL 0x00053, 0x00310>
critical:
Native stacktrace:
2016-12-15 18:23:16.487 Realm0810SynchronizationContext[24731:19379660] [PASS] Realm0810SynchronizationContext.RealmRead.ObjectForPrimaryKey_Sequential
Thread finished: #9
Thread finished: #10
Tests run: 1 Passed: 1 Failed: 0 Skipped: 0
critical: 0 libmonosgen-2.0.dylib 0x000000011a5d9c3d mono_handle_native_sigsegv + 253
critical: 1 libsystem_platform.dylib 0x000000011e44352a _sigtramp + 26
critical: 2 libsystem_c.dylib 0x000000011e1d50b3 suboptarg + 5403
critical: 3 libsystem_c.dylib 0x000000011e1a0fd7 abort + 129
critical: 4 libc++abi.dylib 0x000000011ac6d95a __cxa_bad_cast + 0
critical: 5 libc++abi.dylib 0x000000011ac92ce7 _ZL25default_terminate_handlerv + 243
critical: 6 libobjc.A.dylib 0x000000011acaa4b4 _ZL15_objc_terminatev + 124
critical: 7 libc++abi.dylib 0x000000011ac8fe69 _ZSt11__terminatePFvvE + 8
critical: 8 libc++abi.dylib 0x000000011ac8f8e0 _ZN10__cxxabiv1L22exception_cleanup_funcE19_Unwind_Reason_CodeP17_Unwind_Exception + 0
critical: 9 Realm0810SynchronizationContext 0x000000010f034e62 _ZNK5realm5Realm13verify_threadEv + 80
critical: 10 Realm0810SynchronizationContext 0x000000010f03562e _ZN5realm5Realm6notifyEv + 68
critical: 11 Realm0810SynchronizationContext 0x000000010f018f65 _ZNK5realm5_impl17WeakRealmNotifier8CallbackclEv + 45
critical: 12 ??? 0x00000001346393ce 0x0 + 5173908430
critical: 13 ??? 0x00000001345d2435 0x0 + 5173486645
critical: 14 ??? 0x000000013302362c 0x0 + 5150750252
critical: 15 libmonosgen-2.0.dylib 0x000000011a52e747 mono_jit_runtime_invoke + 2247
critical: 16 libmonosgen-2.0.dylib 0x000000011a6f7638 do_runtime_invoke + 88
critical: 17 libmonosgen-2.0.dylib 0x000000011a6fb070 mono_runtime_try_invoke_array + 1536
critical: 18 libmonosgen-2.0.dylib 0x000000011a6684ee ves_icall_InternalInvoke + 734
critical: 19 ??? 0x00000001331701e2 0x0 + 5152113122
critical: 20 ??? 0x000000013316fad8 0x0 + 5152111320
critical: 21 ??? 0x00000001345b6168 0x0 + 5173371240
critical:
=================================================================
Got a SIGABRT while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================
Code Sample
Xamarin.iOS
app using xUnit for Devices
:
Realm081Test.zip SHA Checksum is : 78ec0beeeb0beb21e6eae718c9c92f6b8ebc6e90
Within the SynchronizationContextCrash.cs
| GenerateDB
method, if you comment out the Realm.WriteAsync
block the crash does not ever happen.
Downgrading the Realm package to 0.80.0 will result in Success: 100 tests
async Task<Realm> GenerateDB(string path)
{
var config = new RealmConfiguration(path)
{
ObjectClasses = new Type[] { typeof(KeyValue) }
};
var cache = Realm.GetInstance(config);
// Commit out the WriteSync, replace with "await Task.FromResult(0);" and the "random" crash goes away
await cache.WriteAsync(r =>
{
// Fetch and write new objects
});
//await Task.FromResult(0);
return cache;
}
Version of Realm and tooling
Realm version(s): 0.81.0 Which operating system version and device: Only iOS has be tested so far (sim & device)
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 18 (9 by maintainers)
Hey @sushihangover,
This is an unfortunate side-effect of our work to support Windows. For 0.81.0 we migrated away from platform-specific code for the iOS RunLoop and Android Looper to an abstraction based on
System.Threading.SynchronizationContext
in order to support more platforms.Most of the
SynchronizationContext
implementations out there - the ones Xamarin built on top of the iOS RunLoop and Android Looper and the ones that come with Windows Forms, WPF, and UWP, are thread-affine in that they always post work on the same thread. xUnit, however, comes with aSynchronizationContext
implementation that uses a dedicated worker thread.The simple workaround is to temporarily unset the current
SynchronizationContext
when opening a realm on a worker thread so that the realm doesn’t capture it:When opening a realm on a thread without a
SynchronizationContext
, the reactive properties of Realm - change events and auto refresh, will be disabled, same as when opening a realm on a thread without a runloop or looper in previous versions.Alternatively, you can use
Nito.AsyncEx.AsyncContext
in your tests which will install aSynchronizationContext
implementation that is thread-affine. This is the library I’m using for running our tests on Windows.There might be further improvements we can come up with to be compatible with more
SynchronizationContext
implementations, which will hopefully eliminate the need for these workarounds.I will re-visit this as I lost the change events for some reason… (great info on the trans/pipe/refresh usage, you should tag that info in an “Advanced Realm threading for Dummies” 😉 section of the docs #1041)
Yes, I have CFRunloops&Loopers (non-UI) so I can post long running user requests, capture network sources, etc…
NP, I’ll put together something and post another comment