Realm-java: Realm.compactRealm on external storage throws RealmError: Unrecoverable error. Read-only file system

Created on 2 Feb 2017  路  11Comments  路  Source: realm/realm-java

Introduction

Hi, I have a complex app with more than one Realm (because of sandboxing) and Realms are stored on External Storage. Until recently I was stuck at v1.0.1 because of various problems that were fixed ;)
But now I'm facing a new problem, the compact phase (which is started before opening the realm) is crashing the whole app. Even if I'm catching the RealmError, a native crash occurs afterwards.

Goal

Compact Realm before opening it, the Realm exists and is writable.

Expected Results

No explosion

Actual Results

io.realm.exceptions.RealmError: Unrecoverable error. Read-only file system in /home/cc/repo/realm/realm-java-release/realm/realm-library/src/main/cpp/io_realm_internal_SharedRealm.cpp line 414
        at io.realm.internal.SharedRealm.nativeCompact(Native Method)
        at io.realm.internal.SharedRealm.compact(SharedRealm.java:327)
        at io.realm.BaseRealm.compactRealm(BaseRealm.java:586)
        at io.realm.Realm.compactRealm(Realm.java:1612)

Steps & Code to Reproduce

Simple AndroidTestCase

public class RealmExternalTest extends AndroidTestCase {

    @Override
    protected void setUp() throws Exception {
        Realm.init(getContext());
    }

    @Override
    protected void tearDown() throws Exception {
    }

    public void testRealmCompactExternal() {
        File directory = getContext().getExternalFilesDir(null);
        directory.mkdirs();

        assertTrue(directory.exists());

        RealmConfiguration config = new RealmConfiguration.Builder().directory(directory).name("somerealm.realm").build();
        Realm realm = Realm.getInstance(config);

        File realmFile = new File(config.getPath());
        assertTrue(realmFile.exists() && realmFile.canWrite());

        { // simple read/write
            Test test = new Test();

            realm.beginTransaction();
            try {
                realm.copyToRealm(test);

                realm.commitTransaction();
            } catch (Exception e) {
                realm.cancelTransaction();
                fail();
            }

            assertTrue(realm.where(Test.class).count() > 0);
        }

        realm.close();

        assertTrue(Realm.compactRealm(config));
    }
}

The whole test is passing, except the last line throwing the above exception :/

Version of Realm and tooling

Realm version(s): 2.3.0

Realm sync feature enabled: no

Android Studio version: 2.2.3

Which Android version and device: Samsung Galaxy Tab S2 (SM-T710) 6.0.1

T-Bug

All 11 comments

Hey @tmeunier ,
I don't have a Galaxy Tab, so I can't verify your issue on the particular device. We do have a bunch of unit tests around compaction, here: https://github.com/realm/realm-java/blob/master/realm/realm-library/src/androidTest/java/io/realm/RealmTests.java

I've also run your specific test on a couple of devices and cannot repro the problem.

Can you try this on another device and see if it is a problem there, as well? If you can get it to fail on a Nexus device, that would be particularly interesting.

Attempted to repro on a Samsung Galaxy Note 8.0, 4.4.2. No joy.

Hey @bmeike
I took a look at the tests but they do not include "compact on external storage" ;)

I ran the following tests on other devices/emulators I have :
A) compact a Realm on internal storage (based on your tests)
B) compact a Realm on external storage (the one above)

Samsung Galaxy Tab S2 (6.0.1)
A) OK
B) KO - io.realm.exceptions.RealmError: Unrecoverable error. Read-only file system

Samsung Galaxy Tab 4 (5.0.2)
A) OK
B) KO - io.realm.exceptions.RealmError: Unrecoverable error. Read-only file system

HTC One M8 (6.0.0)
A) OK
B) KO - io.realm.exceptions.RealmError: Unrecoverable error. Read-only file system

Samsung XCover 3 (5.1.1)
A) OK
B) KO - io.realm.exceptions.RealmError: Unrecoverable error. Read-only file system

Wiko Rainbow Lite 4G (5.1.1)
A) OK
B) KO - io.realm.exceptions.RealmError: Unrecoverable error. Read-only file system

Nexus 5 - emulator/rooted (5.1.0)
A) OK
B) OK

Nexus 5 - emulator/rooted (6.0.0)
A) OK
B) OK

Samsung Galaxy S6 - emulator/rooted (6.0.0)
A) OK
B) OK

So, it's working on emulators but not on my devices... Could you give a try with Android 5+ ?

My apologies! I overlooked this line: File directory = getContext().getExternalFilesDir(null);

Although I don't think this is the problem, can you verify that you are using both android.permission.READ_EXTERNAL_STORAGE and android.permission.WRITE_EXTERNAL_STORAGE permission?

Yes. I can duplicate this on both the Nexus 4 5.1.1 and the Samsung Galaxy Tab 8.0

@bmeike No worries.

Yes, permissions are fine. Also, I'm able to create/read/write the Realm on the external storage, just compact is not working. And before upgrade to 2.3.0 it was working...

Yep. I confirm.

I believe the error is beneath this call in shared_realm.cpp:

Group& Realm::read_group()
{
    verify_open();

    if (!m_group) {
        m_group = &const_cast<Group&>(m_shared_group->begin_read());
        add_schema_change_handler();
    }
    return *m_group;
}

A casual review of the code doesn't show any relevant recent changes.

Also, the file does appear to be available, RW, for the process:

shell@mako:/sdcard/Android/data/io.realm.test/files $ ps
...
u0_a112   18535 18533 1088   508   ffffffff 00000000 S /system/bin/sh
u0_a112   18541 18535 6200   1164  ffffffff 00000000 S /data/data/io.realm.test/lldb/bin/lldb-server
u0_a112   18542 18541 9280   1896  ffffffff 00000000 S /data/data/io.realm.test/lldb/bin/lldb-server
u0_a112   18544 18542 8264   3228  ffffffff 00000000 S /data/data/io.realm.test/lldb/bin/lldb-server
root      18635 2     0      0     ffffffff 00000000 S flush-0:18
shell     18679 18426 2412   716   00000000 b6ec9174 R ps

shell@mako:/sdcard/Android/data/io.realm.test/files $ ls -al
-rw-rw---- u0_a86   sdcard_r   147456 2017-02-03 15:23 somerealm.realm
-rw-rw---- u0_a86   sdcard_r     1160 2017-02-03 15:24 somerealm.realm.lock
drwxrwx--- u0_a86   sdcard_r          2017-02-03 15:22 somerealm.realm.management

shell@mako:/sdcard/Android/data/io.realm.test/files $ id u0_a112           
uid=2000(shell) gid=2000(shell) groups=1003(graphics),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats) context=u:r:shell:s0
sh

I wonder if this is related to #3972 ?

The patch that will allow this test pass is being tracked in https://github.com/realm/realm-core/pull/2445

Good to know, thanks!

need core release v2.3.2

Was this page helpful?
0 / 5 - 0 ratings