Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frozen Realms don't reference count correctly #7521

Open
alecbarber opened this issue Jul 19, 2021 · 1 comment
Open

Frozen Realms don't reference count correctly #7521

alecbarber opened this issue Jul 19, 2021 · 1 comment

Comments

@alecbarber
Copy link

Goal

I would like the following code not to crash.

val realm = Realm.getDefaultInstance()

// Freeze the Realm
val realm1 = realm.freeze()
// Freeze a second time first, then write to the live Realm
val realm2 = realm.freeze()
realm.executeTransaction { ... }

// Close the first frozen instance.
realm1.close()

// Make a query on the second frozen instance
// Throws IllegalStateException, saying that realm2 is closed.
realm2.where<...>().findAll().doSomething()

// Clean up
realm2.close()
realm.close()

Actual Results

The code crashes on querying realm2, saying that realm2 is closed.

Steps & Code to Reproduce

Run the above code.

Version of Realm and tooling

Realm version(s): 10.6.0

Realm Sync feature enabled: No

Android Studio version: 4.2

Android Build Tools version: 4.0.1

Gradle version: 6.7.1

Which Android version and device(s): Android Emulator running 7.1.1 and 9.0

Other comments

The cause of the issue is the reference counting associated with the following code:

val realm1 = Realm.getDefaultInstance().freeze()
val realm2 = Realm.getDefaultInstance().freeze()
// The count of frozen instances at this version of the Realm is 1, not 2
// Now when we close one of our frozen instances, the reference count goes to 0. The shared frozen instance is deallocated.
realm1.close()
// So when we try to do a query on the other instance, an IllegalStateException is thrown.
realm2.where<...>().findAll()

If we insert a write transaction (to an unfrozen instance) between the two freeze() calls, then an exception is no longer thrown because realm1 and realm2 now point at different database versions, rather than sharing a frozen instance. The main issue for me is that this can lead to a race condition between modifying the database and taking a frozen snapshot, with different results depending on who wins.

I submitted a PR (#7504) which I think fixes this – not sure what your guys' workflow is so sorry if that was a bit forward of me :D

@rorbech
Copy link
Contributor

rorbech commented Jul 19, 2021

Hi @alecbarber. Thanks for the detailed report and fix. We will of course have to verify the issue and your fix. Will get back when that is done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants