From ce3d333134ba954dd51114ef68c0458e3f2375bf Mon Sep 17 00:00:00 2001 From: Christian Melchior Date: Fri, 8 Dec 2023 11:56:17 +0100 Subject: [PATCH] Fix using Realm on wrong thread when calculating KeyPaths. (#1594) --- CHANGELOG.md | 30 +++++++++++++++++++ .../io/realm/kotlin/internal/RealmImpl.kt | 4 ++- .../kotlin/internal/SuspendableNotifier.kt | 6 ++-- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9636329320..45f1c98a43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +## 1.13.1-SNAPSHOT (YYYY-MM-DD) + +### Breaking Changes +* None. + +### Enhancements +* None. + +### Fixed +* Using keypaths in Flows could sometimes throw `java.lang.IllegalStateException: [RLM_ERR_WRONG_THREAD]: Realm accessed from incorrect thread.`. (Issue [#1594](https://github.com/realm/realm-kotlin/pull/1594, since 1.13.0) + +### Compatibility +* File format: Generates Realms with file format v23. +* Realm Studio 13.0.0 or above is required to open Realms created by this version. +* This release is compatible with the following Kotlin releases: + * Kotlin 1.9.0 and above. Support for experimental K2-compilation with `kotlin.experimental.tryK2=true`. + * Ktor 2.1.2 and above. + * Coroutines 1.7.0 and above. + * AtomicFu 0.18.3 and above. + * The new memory model only. See https://github.com/realm/realm-kotlin#kotlin-memory-model-and-coroutine-compatibility +* Minimum Kbson 0.3.0. +* Minimum Gradle version: 6.8.3. +* Minimum Android Gradle Plugin version: 4.1.3. +* Minimum Android SDK: 16. +* Minimum R8: 8.0.34. + +### Internal +* None. + + ## 1.13.0 (2023-12-01) ### Breaking Changes diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmImpl.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmImpl.kt index adfef17780..e99972f1ce 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmImpl.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/RealmImpl.kt @@ -23,6 +23,7 @@ import io.realm.kotlin.dynamic.DynamicRealm import io.realm.kotlin.internal.dynamic.DynamicRealmImpl import io.realm.kotlin.internal.interop.ClassKey import io.realm.kotlin.internal.interop.RealmInterop +import io.realm.kotlin.internal.interop.RealmKeyPathArrayPointer import io.realm.kotlin.internal.interop.SynchronizableObject import io.realm.kotlin.internal.platform.copyAssetFile import io.realm.kotlin.internal.platform.fileExists @@ -225,7 +226,8 @@ public class RealmImpl private constructor( } override fun , C> registerObserver(t: Observable, keyPaths: Pair>?): Flow { - return notifier.registerObserver(t, keyPaths) + val keypathsPtr: RealmKeyPathArrayPointer? = keyPaths?.let { RealmInterop.realm_create_key_paths_array(realmReference.dbPointer, keyPaths.first, keyPaths.second) } + return notifier.registerObserver(t, keypathsPtr) } /** diff --git a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/SuspendableNotifier.kt b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/SuspendableNotifier.kt index b3e68aaa7a..e075e86dae 100644 --- a/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/SuspendableNotifier.kt +++ b/packages/library-base/src/commonMain/kotlin/io/realm/kotlin/internal/SuspendableNotifier.kt @@ -2,7 +2,6 @@ package io.realm.kotlin.internal import io.realm.kotlin.VersionId import io.realm.kotlin.internal.interop.Callback -import io.realm.kotlin.internal.interop.ClassKey import io.realm.kotlin.internal.interop.RealmChangesPointer import io.realm.kotlin.internal.interop.RealmInterop import io.realm.kotlin.internal.interop.RealmKeyPathArrayPointer @@ -95,8 +94,7 @@ internal class SuspendableNotifier( return _realmChanged.asSharedFlow() } - internal fun , C> registerObserver(flowable: Observable, keyPaths: Pair>?): Flow { - val keypathsPtr: RealmKeyPathArrayPointer? = keyPaths?.let { RealmInterop.realm_create_key_paths_array(realm.owner.realmReference.dbPointer, keyPaths.first, keyPaths.second) } + internal fun , C> registerObserver(flowable: Observable, keyPathsPtr: RealmKeyPathArrayPointer?): Flow { return callbackFlow { val token: AtomicRef = kotlinx.atomicfu.atomic(NO_OP_NOTIFICATION_TOKEN) @@ -125,7 +123,7 @@ internal class SuspendableNotifier( changeFlow.emit(frozenObservable, change) } } - token.value = NotificationToken(lifeRef.registerForNotification(keypathsPtr, interopCallback)) + token.value = NotificationToken(lifeRef.registerForNotification(keyPathsPtr, interopCallback)) } else { changeFlow.emit(null) }