realm / realm-java

Realm is a mobile database: a replacement for SQLite & ORMs
http://realm.io
Apache License 2.0
11.45k stars 1.75k forks source link

Crash on copyFromRealm for Entities with field RealmList<RealmAny> #7586

Closed vcimka closed 2 years ago

vcimka commented 2 years ago

How frequently does the bug occur?

All the time

Description

Crash on copyFromRealm for Entities with field RealmList<RealmAny> it seems to be playable only on some devices

Stacktrace & log output

A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x8b in tid 30696 (example.testapp), pid 30696 (example.testapp)

       *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'motorola/pettyl/pettyl:8.1.0/OPG28.54-53-8/55beb:user/release-keys'
Revision: 'p300'
ABI: 'arm'
pid: 19549, tid: 19549, name: example.testapp  >>> com.example.testapp <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8b
Cause: null pointer dereference
    r0 00000000  r1 0000007b  r2 0000007b  r3 00000000
    r4 bed1c6b8  r5 00000000  r6 00000000  r7 bed1c698
    r8 00000000  r9 0000007b  sl 00000000  fp bed1c76c
    ip 975c2a99  sp bed1c680  lr 9757e609  pc 9757e608  cpsr 40070030
backtrace:
    #00 pc 001fe608  /data/app/com.example.testapp-4jVqw7f-kkz-6UcIiIozOQ==/lib/arm/librealm-jni.so
    #01 pc 00242aa9  /data/app/com.example.testapp-4jVqw7f-kkz-6UcIiIozOQ==/lib/arm/librealm-jni.so (Java_io_realm_internal_core_NativeRealmAny_nativeGetType+16)
    #02 pc 00021f5f  /data/app/com.example.testapp-4jVqw7f-kkz-6UcIiIozOQ==/oat/arm/base.odex (offset 0x20000)

Can you reproduce the bug?

Yes, always

Reproduction Steps

just run that sample

open class TestEntity(
    @PrimaryKey
    var id: Long = 0,
    var items: RealmList<RealmAny>? = null
) : RealmObject()

class MainActivity : AppCompatActivity() {

    private lateinit var realm: Realm

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        initDb()

        saveEntities()
        getEntities()
    }

    private fun initDb() {
        Realm.init(applicationContext)

        val directory =
            File(applicationContext.filesDir.absolutePath + File.separator + "app_db")

        val config = RealmConfiguration.Builder()
            .directory(directory)
            .deleteRealmIfMigrationNeeded()
            .allowWritesOnUiThread(true)
            .build()

        Realm.setDefaultConfiguration(config)

        realm = Realm.getDefaultInstance()
    }

    private fun getEntities(): List<TestEntity> {
        val results = realm.where(TestEntity::class.java).findAll()
        return realm.copyFromRealm(results)
    }

    private fun saveEntities() {
        val entities = (0..100).realmMap {
            TestEntity(
                id = it.toLong(),
                items = (0..10).realmMap {
                    RealmAny.valueOf(
                        123L
                    )
                }
            )
        }

        realm.executeTransaction {
            realm.insertOrUpdate(entities)
        }
    }

    inline fun <T, R> Iterable<T>.realmMap(transform: (T) -> R): RealmList<R> {
        return mapTo(RealmList(), transform)
    }
}

Version

10.8.1

What SDK flavour are you using?

Local Database only

Are you using encryption?

No, not using encryption

Platform OS and version(s)

Motorolla G5S (XT1794) Android 8.1.0

Build environment

Android Studio version: 2021.1.1 Android Build Tools version: 7.1.0-beta02 Gradle version: 7.2

vcimka commented 2 years ago

Hello, @cmelchior can i help to fix it? please let me know if any details needed that's affected a lot of our users

vcimka commented 2 years ago

same for

val results : RealmResults<TestEntity> = realm.where(TestEntity::class.java).findAll()  
results.firstOrNull()?.items?.map { 
    val innerEntity = it.asLong()
}

or

val result: TestEntity? = realm.where(TestEntity::class.java).findFirst()
val innerItems = result?.items
val mappedInnerItems = innerItems ?.map {
     it.asLong()
}

without copyFromRealm this happens for any calls to nested RealmAny objects

vcimka commented 2 years ago

same on next devices:

Nexus 7 (API 21) SM-G532G (API 23) Redmi 6A (API 27) moto e5 play (API 27) SM-A105FN (API 29) Nexus 5 (API 23) LG-AS110 (API 23) Nokia 1 (API 27)

       *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'samsung/grandppltedx/grandpplte:6.0.1/MMB29T/G532GDXU1APJ5:user/release-keys'
Revision: '0'
ABI: 'arm'
pid: 13023, tid: 13023, name: example.testapp  >>> com.example.testapp <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8b
    r0 00000000  r1 0000007b  r2 0000007b  r3 00000000
    r4 bee80a28  r5 12d9bb60  r6 12c57250  r7 bee80a08
    r8 12c57250  r9 0000007b  sl 00000000  fp 12c57250
    ip b2edca99  sp bee809f0  lr b2e98609  pc b2e98608  cpsr 40070030
backtrace:
    #00 pc 001fe608  /data/app/com.example.testapp-1/lib/arm/librealm-jni.so
    #01 pc 00242aa9  /data/app/com.example.testapp-1/lib/arm/librealm-jni.so (Java_io_realm_internal_core_NativeRealmAny_nativeGetType+16)
    #02 pc 0116f45d  /data/app/com.example.testapp-1/oat/arm/base.odex (offset 0xb99000)
       *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'xiaomi/cactus/cactus:8.1.0/O11019/V10.3.8.0.OCBMIXM:user/release-keys'
Revision: '0'
ABI: 'arm'
pid: 27687, tid: 27687, name: example.testapp  >>> com.example.testapp <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8b
Cause: null pointer dereference
    r0 00000000  r1 0000007b  r2 0000007b  r3 00000000
    r4 be9b15c8  r5 00000000  r6 00000000  r7 be9b15a8
    r8 00000000  r9 0000007b  sl 00000000  fp be9b167c
    ip 93093a99  sp be9b1590  lr 9304f609  pc 9304f608  cpsr 40070030
backtrace:
    #00 pc 001fe608  /data/app/com.example.testapp-5AkCnGTx2RJO0FJL1bWPNQ==/lib/arm/librealm-jni.so
    #01 pc 001fe607  /data/app/com.example.testapp-5AkCnGTx2RJO0FJL1bWPNQ==/lib/arm/librealm-jni.so
       *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'motorola/pettyl/pettyl:8.1.0/OPG28.54-53-8/55beb:user/release-keys'
Revision: 'p300'
ABI: 'arm'
pid: 19549, tid: 19549, name: example.testapp  >>> com.example.testapp <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8b
Cause: null pointer dereference
    r0 00000000  r1 0000007b  r2 0000007b  r3 00000000
    r4 bed1c6b8  r5 00000000  r6 00000000  r7 bed1c698
    r8 00000000  r9 0000007b  sl 00000000  fp bed1c76c
    ip 975c2a99  sp bed1c680  lr 9757e609  pc 9757e608  cpsr 40070030
backtrace:
    #00 pc 001fe608  /data/app/com.example.testapp-4jVqw7f-kkz-6UcIiIozOQ==/lib/arm/librealm-jni.so
    #01 pc 00242aa9  /data/app/com.example.testapp-4jVqw7f-kkz-6UcIiIozOQ==/lib/arm/librealm-jni.so (Java_io_realm_internal_core_NativeRealmAny_nativeGetType+16)
    #02 pc 00021f5f  /data/app/com.example.testapp-4jVqw7f-kkz-6UcIiIozOQ==/oat/arm/base.odex (offset 0x20000)
      *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'samsung/a10eea/a10:10/QP1A.190711.020/A105FNXXS6BUB1:user/release-keys'
Revision: '5'
ABI: 'arm'
Timestamp: 2021-11-25 01:59:13-0800
pid: 16058, tid: 16058, name: example.testapp  >>> com.example.testapp <<<
uid: 10220
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8b
Cause: null pointer dereference
    r0  00000000  r1  0000007b  r2  0000007b  r3  00000000
    r4  ff82ca68  r5  00000004  r6  e7876800  r7  ff82ca48
    r8  00000000  r9  0000007b  r10 ff82cb98  r11 ff82cb1c
    ip  b62cda99  sp  ff82ca30  lr  b6289609  pc  b6289608
       *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/hammerhead/hammerhead:6.0.1/M4B30Z/3437181:user/release-keys'
Revision: '0'
ABI: 'arm'
pid: 30587, tid: 30587, name: example.testapp  >>> com.example.testapp <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8b
    r0 00000000  r1 0000007b  r2 0000007b  r3 00000000
    r4 bef7ad48  r5 12e957e0  r6 12e479d0  r7 bef7ad28
    r8 12e479d0  r9 0000007b  sl 00000000  fp 12e479d0
    ip a0bb3a99  sp bef7ad10  lr a0b6f609  pc a0b6f608  cpsr 40070030
backtrace:
    #00 pc 001fe608  /data/app/com.example.testapp-1/lib/arm/librealm-jni.so
    #01 pc 00242aa9  /data/app/com.example.testapp-1/lib/arm/librealm-jni.so (Java_io_realm_internal_core_NativeRealmAny_nativeGetType+16)
    #02 pc 0116b995  /data/app/com.example.testapp-1/oat/arm/base.odex (offset 0xb98000)
      *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'lge/lv0_trf_us/lv0:6.0.1/MXB48T/1705410450712:user/release-keys'
Revision: '0'
ABI: 'arm'
pid: 13534, tid: 13534, name: example.testapp  >>> com.example.testapp <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8b
    r0 00000000  r1 0000007b  r2 0000007b  r3 00000000
    r4 bec67b38  r5 12d986e0  r6 12ccb850  r7 bec67b18
    r8 12ccb850  r9 0000007b  sl 00000000  fp 12ccb850
    ip 9ff03a99  sp bec67b00  lr 9febf609  pc 9febf608  cpsr 40070030
backtrace:
    #00 pc 001fe608  /data/app/com.example.testapp-1/lib/arm/librealm-jni.so
    #01 pc 00242aa9  /data/app/com.example.testapp-1/lib/arm/librealm-jni.so (Java_io_realm_internal_core_NativeRealmAny_nativeGetType+16)
    #02 pc 0116b9cd  /data/app/com.example.testapp-1/oat/arm/base.odex (offset 0xb98000)
       *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'Nokia/Frontier_00WW/FRT:8.1.0/O11019/00WW_1_33A:user/release-keys'
Revision: '0'
ABI: 'arm'
pid: 20728, tid: 20728, name: example.testapp  >>> com.example.testapp <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8b
Cause: null pointer dereference
    r0 00000000  r1 0000007b  r2 0000007b  r3 00000000
    r4 bed12748  r5 00000000  r6 00000000  r7 bed12728
    r8 00000000  r9 0000007b  sl 00000000  fp bed12804
    ip 94994a99  sp bed12710  lr 94950609  pc 94950608  cpsr 40070030
backtrace:
    #00 pc 001fe608  /data/app/com.example.testapp-25ybol8wOm19VVlcAVIXxQ==/lib/arm/librealm-jni.so
    #01 pc 00242aa9  /data/app/com.example.testapp-25ybol8wOm19VVlcAVIXxQ==/lib/arm/librealm-jni.so (Java_io_realm_internal_core_NativeRealmAny_nativeGetType+16)
    #02 pc 00021f5f  /data/app/com.example.testapp-25ybol8wOm19VVlcAVIXxQ==/oat/arm/base.odex (offset 0x20000)
vcimka commented 2 years ago

hello @cmelchior can we fix it?

cmelchior commented 2 years ago

Hi @Stefanos65535

Looking into this. I'm not sure it is directly related to copyFromRealm() as you also mention this failing https://github.com/realm/realm-java/issues/7586#issuecomment-974612765

I tried to reproduce using your code, but at least it seems to run fine on both x86 and x86_64 emulators.

So maybe this is some kind of race condition being triggered on those devices 🤔

vcimka commented 2 years ago

@cmelchior thanks for replay on emulators run fine too but on ARM physical devices got crashes everytime when any call to RealmList<RealmAny> happen we tried to run that sample as a robo test on firebase Test Lab on physical devices and it got crashed on more than 10% (9 of 77) of devices (list of devices in the post above)

cmelchior commented 2 years ago

Thank you...all of those look like pretty old devices, which could point to a race condition. Unfortunately, I don't have either of them.

I tried to reproduce on both a Oneplus 5T and a Oneplus 8 Pro, both of these work fine.

Internal note: I did try to see if we by accident release the native reference to the RealmAny value, which could cause something like this if the GC kicks in at the wrong time, but from what I could tell, we do keep the native reference alive alongside the public RealmAny public object.

vcimka commented 2 years ago

@cmelchior Yes, I understand it works correctly on many devices, but there are also many reverse cases. for example Samsung Galaxy A10 (SM-A105FN) with Android 9.0 far from old device Maybe i can help you with repro? I have one device from list. Maybe I should configure everything for remote access? so you can try it yourself on my device? error reproducible 100 out of 100 cases

vcimka commented 2 years ago

@cmelchior a bit more info tried with next sample:

open class FirstInnerTestEntity(
    @PrimaryKey
    var id: Long = 0
) : RealmObject()

open class SecondInnerTestEntity(
    @PrimaryKey
    var id: Long = 0
) : RealmObject()

open class TestEntity(
    @PrimaryKey
    var id: Long = 0,
    var items: RealmList<FirstInnerTestEntity>? = null
) : RealmObject()

open class WithRealmAnyTestEntity(
    @PrimaryKey
    var id: Long = 0,
    var items: RealmList<RealmAny>? = null
) : RealmObject()

class MainActivity : AppCompatActivity() {

    private lateinit var realm: Realm

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        initDb()

        saveEntities()

        getEntities(FirstInnerTestEntity::class.java)
        getEntities(SecondInnerTestEntity::class.java)
        getEntities(TestEntity::class.java)
        getEntities(WithRealmAnyTestEntity::class.java)

        setContentView(R.layout.activity_main)
    }

    private fun initDb() {
        Realm.init(applicationContext)

        val directory =
            File(applicationContext.filesDir.absolutePath + File.separator + "app_db")

        val config = RealmConfiguration.Builder()
            .directory(directory)
            .deleteRealmIfMigrationNeeded()
            .allowWritesOnUiThread(true)
            .build()

        Realm.setDefaultConfiguration(config)

        realm = Realm.getDefaultInstance()
    }

    private fun <C: RealmModel> getEntities(clazz: Class<C>): List<C> {
        val results = realm.where(clazz).findAll()
        return realm.copyFromRealm(results)
    }

    private fun saveEntities() {
        val entities = (0..100).realmMap {
            TestEntity(
                id = it.toLong(),
                items = (0..10).realmMap {
                    FirstInnerTestEntity(
                        Random.nextLong()
                    )
                }
            )
        }
        val entities2 = (0..100).realmMap {
            WithRealmAnyTestEntity(
                id = it.toLong(),
                items = (0..10).realmMap {
                    RealmAny.valueOf(
                        when (Random.nextBoolean()) {
                            true -> FirstInnerTestEntity(
                                Random.nextLong()
                            )
                            false -> SecondInnerTestEntity(
                                Random.nextLong()
                            )
                        }
                    )
                }
            )
        }

        realm.executeTransaction {
            realm.insertOrUpdate(entities)
            realm.insertOrUpdate(entities2)
        }
    }

    inline fun <T, R> Iterable<T>.realmMap(transform: (T) -> R): RealmList<R> {
        return mapTo(RealmList(), transform)
    }
}

stacktrace:


<unknown> 0x0000000091680608
Java_io_realm_internal_core_NativeRealmAny_nativeGetType 0x00000000916c4aac
int io.realm.internal.core.NativeRealmAny.nativeGetType(long) 0x0000000091a57c08
art_quick_invoke_stub_internal 0x00000000ac583376
art_quick_invoke_static_stub 0x00000000ac5885ee
art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*) 0x00000000ac2300e2

image

ipolotsky commented 2 years ago

I have the very same issue

Raingava commented 2 years ago

I get requests from users with a similar problem

vcimka commented 2 years ago

@cmelchior any updates?

vcimka commented 2 years ago

hello @cmelchior on version 10.9.0 there are no more crashes but the RealmList<RealmAny> is now returning as a list of NULL objects image

rorbech commented 2 years ago

Seems to be the same root cause as in #7626. Will close this one.