Realm-java: SIGSEV signal 11

Created on 25 Sep 2016  Â·  17Comments  Â·  Source: realm/realm-java

Goal

Use the library

Expected Results

No sigsev

Actual Results

Here's the error code:

Fatal signal 11 (SIGSEGV), code 1, fault addr 0x14c in tid 7837 (ator.app)

Here's the "Build Fingerprint:"

Build fingerprint: 'generic/vbox86p/vbox86p:5.0/LRX21M/buildbot11172321:userdebug/test-keys'
26643-26643/? I/DEBUG: Revision: '0'
26643-26643/? I/DEBUG: ABI: 'x86'
26643-26643/? I/DEBUG: pid: 7837, tid: 7837, name: ator.app  >>> com.lockedout.app <<<
26643-26643/? I/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x14c
26643-26643/? I/DEBUG:     eax 00000148  ebx ffffffff  ecx 7470d340  edx 00000002
26643-26643/? I/DEBUG:     esi 00000000  edi 00000002
26643-26643/? I/DEBUG:     xcs 00000023  xds 0000002b  xes 0000002b  xfs 00000007  xss 0000002b
26643-26643/? I/DEBUG:     eip e2f6d025  ebp ffd3cd58  esp ffd3cd50  flags 00210246
26643-26643/? I/DEBUG: backtrace:
26643-26643/? I/DEBUG:     #00 pc 0002a025  /data/app/com.lockedout.app-1/lib/x86/librealm-jni.so
26643-26643/? I/DEBUG:     #01 pc 0009c141  /data/app/com.lockedout.app-1/lib/x86/librealm-jni.so
26643-26643/? I/DEBUG:     #02 pc 0009c299  /data/app/com.lockedout.app-1/lib/x86/librealm-jni.so
26643-26643/? I/DEBUG:     #03 pc 004002d3  /data/dalvik-cache/x86/data@[email protected]@[email protected]
26643-26643/? I/DEBUG:     #04 pc 00000002  <unknown>
26643-26643/? I/DEBUG: Tombstone written to: /data/tombstones/tombstone_06

Steps & Code to Reproduce

Happens when I call notifyDataSetChanged on a RecyclerView.Adapter after I've deleted an Item (extends RealmObject) from a User's (also extends RealmObject) list of Items. In order for you to better understand what the RecyclerView.Adapter's holding, I need to explain the design:

There are 4 possible Items a User can have, each with their own unique id (1-4). The User may not have all of them though, so when I show a user the list of all the possible Items they can have I need to show both the ones they do and the ones they don't have. So there is an ItemWrapper (does not extend RealmObject) to help with that. The adapter holds onto a list of ItemWrappers and if say the User doesn't have Items 1 or 3, then then the 1st and 3rd wrappers in the RecyclerView.Adapter (positions 0 and 2) will have a null Item field. The Item that the ItemWraper wraps is the managed RealmObject that is in the User's list of Items

notifyDataSetChanged is called within the onChange() of a RealmChangeListener, set on the User object. When onChange is called, I create a new list of ItemWrappers using the User's Item list, swap out the old list of ItemWrappers on the adapter with the new one, and then call notifyDataSetChanged.

The error does not occur if I do not call notifyDataSetChanged.

Version of Realm and tooling

Realm version(s): 1.2.0

Android Studio version: 2.1.1

Which Android version and device: Google Nexus 5, Android 5.0.0, API 21

O-Community Pipeline-On-Hold Reproduction-Required T-Bug-Crash

Most helpful comment

@biagionicp what is the getter you called on your RealmObject? I think we should throw a clear exception in this case instead of a native crash.

All 17 comments

fixed the problem. it was being caused by calling a get method on an invalid RealmObject.

why wouldn't this throw a Java exception?

@biagionicp what is the getter you called on your RealmObject? I think we should throw a clear exception in this case instead of a native crash.

@biagionicp Can you show the code for that? Because we try to catch all codepaths that could cause seg faults, but you seem to have found a path that doesnt'?

i have an Integer field in my class and all the get method does is this:

public Integer getClassId() {
        return mClassId;
}

Can you show the entire class?

@beeender @cmelchior

public class Item extends RealmObject {
    private Integer mId;
    public Integer mTally;
    private Integer mClassId;

    public Item(){
    }

    public Item(Integer classId, Integer id){
        mClassId = classId;
        mId = id;
    }

    public Integer getId() {
        return mId;
    }

    public String getTitlePlural() {
        return Items.TITLES.get(mId).getTitlePlural();
    }

    public String getTitleSingular(){
        switch (mClassId){
                case 1:
                    return mId.toString();
                case 3:
                    return GlobalState.DECIMAL_FORMAT.format(UserSingleton.getUser().getScore());
        }
        return Items.TITLES.get(mId).getTitleSingular();
    }

    public void setTally(Integer tally) {
        mTally = tally;
    }

    public Integer getClassId() {
        return mClassId;
    }

    public void setId(Integer id) {
        mId = id;
    }

    public Long getDefiningValue(){
        switch (mClassId.intValue()){
            case 1:
                try {
                    return UserSingleton.getUser().getBirthdate().getTime();
                } catch (Exception e) {
                    return null;
                }
            case 3:
                try {
                    return UserSingleton.getUser().getScore().longValue();
                } catch (Exception e) {
                    return null;
                }
        }
        return mId.longValue();
    }
}

Does hungarian notation work for Realm object fields?

Although even if due to naming convention there are additional setters / getters created, that still shouldn't make Realm crash. So this is a very odd problem.

Here's the method that causes it:
*inside UncheckedRow

@Override
public boolean isNull(long columnIndex) {
    return nativeIsNull(nativePointer, columnIndex);
}

@biagionicp Thanks a lot. We will look into it

I wish I knew the code for UserSingleton :/

Still this sounds like something that'd be fixed by requerying the object inside the transaction, but it's also rather interesting that it'd be out of date in the first place.

I also wonder if hungarian notation has anything to do with it.

@Zhuinden after i spoke with you on SO, that's exactly what i did -- requeried for the User object inside the transactions and made them asynchronous.

Did it work? Or did THAT result in THIS crash?

no. what i'm doing is checking RealmObject.isValid before i start accessing it in my RecyclerView.ViewHolder's bind method

.... How odd, your object gets invalidated. Even then you should get "this Realm instance has been closed and is no longer valid to operate on"

We discovered through the work on #3834 another possible cause for this.
_If_ you do a local write that delete some elements and then trigger View.measure() through some code path, then it is very possible that the RecyclerView will try to access the deleted object behind the scenes, which can cause undefined behaviour.

I encountered the same problem with the proxyState.getRow$realm().isNull() throwing the SIGSEV because a focus listener on a text field fired after having just deleted the RealmObject.

Finding the cause of the SIGSEV is a real pain as you have to breakpoint the all the generated MyClassRealmProxyrealmGet$myField() methods to be able to catch it before it crashes.

Outdated. Closing due to inactivity. If this is still a problem feel free to re-open this issue.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yuwu picture yuwu  Â·  3Comments

mithrann picture mithrann  Â·  3Comments

CNyezi picture CNyezi  Â·  3Comments

jjorian picture jjorian  Â·  3Comments

harshvishu picture harshvishu  Â·  3Comments