Realm-dotnet: Realms.MarshalHelpers GetString and GetInt Crash 0.82.0

Created on 26 Jan 2017  路  16Comments  路  Source: realm/realm-dotnet

Bug:

Goal

A list of realm objects in a list view when selected pass an object property to a new content page.

Expected Results

The property is passed the the new content page

Actual Results

IMPORTANT: if you see this error, please send this log to [email protected] 10:47:28.989 AltecService.iOS[91703:931565] critical: Stacktrace:

2017-01-25 10:47:28.989 AltecService.iOS[91703:931565] critical: at <0xffffffff>
2017-01-25 10:47:28.989 AltecService.iOS[91703:931565] critical: at (wrapper managed-to-native) Realms.ObjectHandle/NativeMethods.get_string (Realms.ObjectHandle,intptr,intptr,intptr,bool&,Realms.NativeException&) <0x00015>
2017-01-25 10:47:28.989 AltecService.iOS[91703:931565] critical: at Realms.ObjectHandle/c__AnonStorey0.<>m__0 (intptr,intptr,bool&,Realms.NativeException&) [0x00011] in <6524e2bca61840fe83e3b491caf456a5>:0
2017-01-25 10:47:28.990 AltecService.iOS[91703:931565] critical: at Realms.MarshalHelpers.GetString (Realms.MarshalHelpers/NativeStringGetter) [0x00020] in <6524e2bca61840fe83e3b491caf456a5>:0
2017-01-25 10:47:28.990 AltecService.iOS[91703:931565] critical: at Realms.ObjectHandle.GetString (intptr) [0x00020] in <6524e2bca61840fe83e3b491caf456a5>:0
2017-01-25 10:47:28.990 AltecService.iOS[91703:931565] critical: at Realms.RealmObject.GetStringValue (string) [0x00017] in <6524e2bca61840fe83e3b491caf456a5>:0
2017-01-25 10:47:28.990 AltecService.iOS[91703:931565] critical: at AltecService.ServiceRequest.get_SrId () [0x0000e] in <4450bc0b11de4d928513a7beccb7f821>:0
2017-01-25 10:47:28.990 AltecService.iOS[91703:931565] critical: at AltecService.ServiceRequestsPage.srSelected (object,Xamarin.Forms.SelectedItemChangedEventArgs) [0x0002b] in /Users/kmrichar/Documents/Git/altec-service/AltecService/Pages/ServiceRequest/ServiceRequests/ServiceRequestsPage.cs:156
2017-01-25 10:47:28.990 AltecService.iOS[91703:931565] critical: at (wrapper delegate-invoke) System.EventHandler`1.invoke_void_object_TEventArgs (object,TEventArgs_REF) [0x00073] in <69565aa0839a4d2ba7987962c4848340>:0
2017-01-25 10:47:28.991 AltecService.iOS[91703:931565] critical: at Xamarin.Forms.ListView.OnSelectedItemChanged (Xamarin.Forms.BindableObject,object,object) [0x0000f] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Core\ListView.cs:588
2017-01-25 10:47:28.991 AltecService.iOS[91703:931565] critical: at Xamarin.Forms.BindableObject.SetValueActual (Xamarin.Forms.BindableProperty,Xamarin.Forms.BindableObject/BindablePropertyContext,object,bool,Xamarin.Forms.BindableObject/SetValueFlags,bool) [0x00108] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Core\BindableObject.cs:584
2017-01-25 10:47:28.991 AltecService.iOS[91703:931565] critical: at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty,object,Xamarin.Forms.BindableObject/SetValueFlags,Xamarin.Forms.BindableObject/SetValuePrivateFlags) [0x0014b] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Core\BindableObject.cs:378
2017-01-25 10:47:28.991 AltecService.iOS[91703:931565] critical: at Xamarin.Forms.BindableObject.SetValueCore (Xamarin.Forms.BindableProperty,object,Xamarin.Forms.BindableObject/SetValueFlags) [0x00000] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Core\BindableObject.cs:324
2017-01-25 10:47:28.991 AltecService.iOS[91703:931565] critical: at Xamarin.Forms.ListView.NotifyRowTapped (int,int,Xamarin.Forms.Cell) [0x00040] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Core\ListView.cs:408
2017-01-25 10:47:28.992 AltecService.iOS[91703:931565] critical: at Xamarin.Forms.ListView.Xamarin.Forms.IListViewController.NotifyRowTapped (int,int,Xamarin.Forms.Cell) [0x00000] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Core\ListView.cs:435
2017-01-25 10:47:28.992 AltecService.iOS[91703:931565] critical: at Xamarin.Forms.Platform.iOS.ListViewRenderer/ListViewDataSource.RowSelected (UIKit.UITableView,Foundation.NSIndexPath) [0x00047] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Platform.iOS\Renderers\ListViewRenderer.cs:850
2017-01-25 10:47:28.992 AltecService.iOS[91703:931565] critical: at (wrapper runtime-invoke) .runtime_invoke_void__this___object_object (object,intptr,intptr,intptr) [0x0005b] in :0
2017-01-25 10:47:28.992 AltecService.iOS[91703:931565] critical: at <0xffffffff>
2017-01-25 10:47:28.992 AltecService.iOS[91703:931565] critical: at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <0x00015>
2017-01-25 10:47:28.993 AltecService.iOS[91703:931565] critical: at UIKit.UIApplication.Main (string[],intptr,intptr) [0x00005] in /Users/builder/data/lanes/3985/4e311372/source/xamarin-macios/src/UIKit/UIApplication.cs:79
2017-01-25 10:47:28.993 AltecService.iOS[91703:931565] critical: at UIKit.UIApplication.Main (string[],string,string) [0x00038] in /Users/builder/data/lanes/3985/4e311372/source/xamarin-macios/src/UIKit/UIApplication.cs:63
2017-01-25 10:47:28.993 AltecService.iOS[91703:931565] critical: at AltecService.iOS.Application.Main (string[]) [0x00008] in /Users/kmrichar/Documents/Git/altec-service/iOS/Main.cs:12
2017-01-25 10:47:28.993 AltecService.iOS[91703:931565] critical: at (wrapper runtime-invoke) .runtime_invoke_void_object (object,intptr,intptr,intptr) [0x00051] in <4450bc0b11de4d928513a7beccb7f821>:0

Steps & Code to Reproduce

Run sample project => select an object from the list => make a transaction => go back to the list of objects => select another object => go back to the list of objects => select another object => Crash

Code Sample

https://www.dropbox.com/s/u1nyrtxd9z0r7xp/realmMashallerIssue.zip?dl=0

Version of Realm and tooling

Realm version(s): 0.82.0

Xamarin/Visual Studio version: Xamarin Studio: 6.2

Which operating system version and device: iOS and Android

Blocked T-Bug-Crash

All 16 comments

Hi Kyle, thanks a lot for the easy to reproduce bug report. We identified the bug and will try to release fix shortly. For now we recommend that you roll back to 0.81.0. If you're interested, here's the issue in ObjectStore (one of our components) that tracks progress toward fixing the bug: https://github.com/realm/realm-object-store/issues/358.

No problem guys always a pleasure :)

This has been fixed in 0.82.1.

@nirinchev So this solved my original issue but I am now getting an InvalidatedException: "Access to invalidated List object" was there any changes from 0.81.0 => 0.82.1 that would cause this to be thrown. I am doing a make shift "Cascading Delete" on an old version of a deeply nested object then writing the new version of the object to realm. It is being thrown while writing the new object but does not throw if I comment out my cascading delete.

Not to my knowledge, but there were some changes in Object Store that might have surfaced the problem. I hate to ask you about it, but if you manage to isolate a repro case, that would be awesome.

Haha not a problem I'll whip together another sample project and email you the link.

That's great, thanks a bunch!

@nirinchev So I am having a difficult time replicating this issue in a test project does this Stack Trace give you any idea as to the cause (my UI is subscribing to updates to specific realm queries but I am disposing of the realm before beginning the sync to sever those connections ) :

at Realms.NativeException.ThrowIfNecessary (System.Func2[T,TResult] overrider) [0x00014] in <fc709facc61843208e1946d37ae6a10c>:0 at Realms.ListHandle.Count () [0x00009] in <fc709facc61843208e1946d37ae6a10c>:0 at Realms.RealmCollectionBase1[T].get_Count () [0x00022] in :0
at Xamarin.Forms.ReadOnlyListAdapter.get_Count () [0x00000] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Core\ReadOnlyListAdapter.cs:31
at Xamarin.Forms.ListProxy.get_Count () [0x00008] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Core\ListProxy.cs:107
at Xamarin.Forms.ListProxy.OnCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00076] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Core\ListProxy.cs:218
at Xamarin.Forms.ListProxy+WeakNotifyProxy.OnCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00031] in C:\BuildAgent2\work\ca3766cfc22354a1\Xamarin.Forms.Core\ListProxy.cs:386
at Realms.RealmCollectionBase1[T].RaiseCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs args) [0x0000d] in <fc709facc61843208e1946d37ae6a10c>:0 at Realms.RealmCollectionBase1[T].OnChange (Realms.IRealmCollection1[T] sender, Realms.ChangeSet change, System.Exception error) [0x0021a] in <fc709facc61843208e1946d37ae6a10c>:0 at Realms.RealmCollectionBase1[T].Realms.RealmCollectionNativeHelper.Interface.NotifyCallbacks (System.Nullable1[T] changes, System.Nullable1[T] exception) [0x00124] in :0
at Realms.RealmCollectionNativeHelper.NotificationCallbackImpl (System.IntPtr managedResultsHandle, System.IntPtr changes, System.IntPtr exception) [0x00033] in :0
at (wrapper native-to-managed) Realms.RealmCollectionNativeHelper:NotificationCallbackImpl (intptr,intptr,intptr)
--- End of stack trace from previous location where exception was thrown ---
at (wrapper managed-to-native) System.Object:wrapper_native_0x17118e (intptr)
at Realms.SynchronizationContextEventLoopSignal+EventLoop+c__AnonStorey0.<>m__0 (System.Object _) [0x00012] in :0
at UIKit.UIKitSynchronizationContext+c__AnonStorey0.<>m__0 () [0x00000] in /Users/builder/data/lanes/3985/4e311372/source/xamarin-macios/src/UIKit/UIKitSynchronizationContext.cs:24
at Foundation.NSAsyncActionDispatcher.Apply () [0x00000] in /Users/builder/data/lanes/3985/4e311372/source/xamarin-macios/src/Foundation/NSAction.cs:163
--- End of stack trace from previous location where exception was thrown ---
at (wrapper managed-to-native) UIKit.UIApplication:UIApplicationMain (int,string[],intptr,intptr)
at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Users/builder/data/lanes/3985/4e311372/source/xamarin-macios/src/UIKit/UIApplication.cs:79
at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x00038] in /Users/builder/data/lanes/3985/4e311372/source/xamarin-macios/src/UIKit/UIApplication.cs:63
at AltecService.iOS.Application.Main (System.String[] args) [0x00008] in /Users/kmrichar/Documents/Git/altec-service/iOS/Main.cs:12

It appears that CollectionChanged is raised, which in turn triggers the binding to try and invoke List.Count. If your Realm is disposed at that time, that would throw the exception you are observing. In general, if you have UI elements bound to Realm collections/objects, you should keep around the Realm to avoid binding-related crashes.

@nirinchev so I have tried to check all my bindings and nothing seems to be tied to the objects being updated I feel like I have been staring at this for hours and I think I am just missing something. I have a lot of WriteAsyncs chained up together. It seems to continue to fail everything when I remove something from realm then try to write the new object almost like realm is not getting the updates from the thread that is making the delete. When I roll back to 0.81.0 everything works without crashing.

Do you think it would be possible to share your solution privately? We can sign an NDA if required. If I could see the code I would be able to offer much more relevant solutions.

public async System.Threading.Tasks.Task MergeObjects()
        {
            //REMOVE OBJECTS NO LONGER IN RESULT SET
            foreach (Object o in _realm.All<Object>().ToList())
            {
                var x = BackgroundSync.RemoteObjects.Where(i => i.Id == o.Id).FirstOrDefault();
                if (x == null)
                {
                    CascadeingObjectDelete(o);
                }
            }
            foreach (Object o in BackgroundSync.RemoteObjects.ToList())
            {
                var x = _realm.All<Object>().Where(i => i.Id == o.Id).FirstOrDefault();
                //WRITE NEW OBJECTS FROM RESULT SET
                if (x == null)
                {
                    await _realm.WriteAsync(tempRealm =>
                    {
                        var content = JsonConvert.SerializeObject(o);
                        var NewObject = new Object();
                        JsonConvert.PopulateObject(content, NewObject);
                        tempRealm.Add(NewObject);
                    });
                }
                else
                {
                                        //DOSE OLD OBJECTS NEED TO BE REPLACED BY UPDATED OBJECT
                    var stamp = x.ObjectDatestamp;
                    int compare = ((DateTimeOffset)sr.ObjectDatestamp).CompareTo(((DateTimeOffset)stamp));
                    if (compare > 0)
                    {
                        CascadeingObjectDelete(o);
//---->>>>> HERE IS WHERE IT IS THROWING ACCESS TO INVALID LIST REALM EXCEPTION <<<
                        await _realm.WriteAsync(tempRealm =>
                        {
                            var content = JsonConvert.SerializeObject(o);
                            var NewObject = new Object();
                            JsonConvert.PopulateObject(content, NewObject);
                            tempRealm.Add(NewObject);
                        });
                    }
                }
            }
        }
public void CascadeingObjectDelete(Object o){
            _realm.Write(() =>
            {
                foreach (var r in o.Attachments.ToList())
                {
                    _realm.Remove(r);
                }
                foreach (var r in o.Comments.ToList())
                {
                    _realm.Remove(r);
                }
                foreach (var r in o.Contacts.ToList())
                {
                    _realm.Remove(r);
                }
                foreach (var r in o.Counters.ToList())
                {
                    _realm.Remove(r);
                }
                foreach (var r in o.Notes.ToList())
                {
                    _realm.Remove(r);
                }
                foreach (var r in SR.Tasks.ToList())
                {
                    foreach (var x in r.Assignments.ToList())
                    {
                        foreach (var t in x.Other.ToList())
                        {
                            foreach (var z in t.Other1.ToList())
                            {
                                _realm.Remove(z);
                            }
                            foreach (var z in t.Other2.ToList())
                            {
                                _realm.Remove(z);
                            }
                            foreach (var z in t.Other3.ToList())
                            {
                                _realm.Remove(z);
                            }
                            foreach (var z in t.Notes.ToList())
                            {
                                _realm.Remove(z);
                            }
                            _realm.Remove(t);
                        }
                        _realm.Remove(x);
                    }
                    foreach (var x in r.Attachments.ToList())
                    {
                        _realm.Remove(x);
                    }
                    foreach (var x in r.Comments.ToList())
                    {
                        _realm.Remove(x);
                    }
                    foreach (var x in r.Notes.ToList())
                    {
                        _realm.Remove(x);
                    }
                    _realm.Remove(r);
                }
                _realm.Remove(o);  // lastly remove the parent 
            });
        }

I can get an NDA approved by tomorrow to share the solution just need to get the right people to ok it.

@nirinchev So an update I apparently solved it with two lines line just needed to sleep on it... :(

---> tempRealm.Add(NewObject, true);
and then do not do the cascading delete on an object that already exists

public async System.Threading.Tasks.Task MergeObjects()
        {
            //REMOVE OBJECTS NO LONGER IN RESULT SET
            foreach (Object o in _realm.All<Object>().ToList())
            {
                var x = BackgroundSync.RemoteObjects.Where(i => i.Id == o.Id).FirstOrDefault();
                if (x == null)
                {
                    CascadeingObjectDelete(o);
                }
            }
            foreach (Object o in BackgroundSync.RemoteObjects.ToList())
            {
                var x = _realm.All<Object>().Where(i => i.Id == o.Id).FirstOrDefault();
                //WRITE NEW OBJECTS FROM RESULT SET
                if (x == null)
                {
                    await _realm.WriteAsync(tempRealm =>
                    {
                        var content = JsonConvert.SerializeObject(o);
                        var NewObject = new Object();
                        JsonConvert.PopulateObject(content, NewObject);
                        tempRealm.Add(NewObject, true);
                    });
                }
                else
                {
                                        //DOSE OLD OBJECTS NEED TO BE REPLACED BY UPDATED OBJECT
                    var stamp = x.ObjectDatestamp;
                    int compare = ((DateTimeOffset)sr.ObjectDatestamp).CompareTo(((DateTimeOffset)stamp));
                    if (compare > 0)
                    {
                        await _realm.WriteAsync(tempRealm =>
                        {
                            var content = JsonConvert.SerializeObject(o);
                            var NewObject = new Object();
                            JsonConvert.PopulateObject(content, NewObject);
                            tempRealm.Add(NewObject, true);
                        });
                    }
                }
            }
        }

Glad to hear that :)

Was this page helpful?
0 / 5 - 0 ratings