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

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

Closed
tmeunier opened this issue Feb 2, 2017 · 11 comments
Labels
Milestone

Comments

@tmeunier
Copy link

tmeunier commented Feb 2, 2017

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

@bmeike bmeike self-assigned this Feb 2, 2017
@bmeike
Copy link
Contributor

bmeike commented Feb 2, 2017

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.

@bmeike
Copy link
Contributor

bmeike commented Feb 3, 2017

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

@tmeunier
Copy link
Author

tmeunier commented Feb 3, 2017

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+ ?

@bmeike
Copy link
Contributor

bmeike commented Feb 3, 2017

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?

@bmeike
Copy link
Contributor

bmeike commented Feb 3, 2017

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

@tmeunier
Copy link
Author

tmeunier commented Feb 3, 2017

@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...

@bmeike
Copy link
Contributor

bmeike commented Feb 3, 2017

Yep. I confirm.

@bmeike bmeike removed their assignment Feb 3, 2017
@bmeike
Copy link
Contributor

bmeike commented Feb 4, 2017

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 ?

bmeike pushed a commit that referenced this issue Feb 4, 2017
bmeike pushed a commit that referenced this issue Feb 6, 2017
@cmelchior cmelchior added this to the 2.4 milestone Feb 7, 2017
beeender added a commit to realm/realm-core that referenced this issue Feb 13, 2017
When compacting the Realm on external storage for Android, SharedGroup
always uses the default sys_tmp_dir which is invalid for Android. Thus
we need an API for setting the default sys_tmp_dir for bindings.
The getters is also required since ObjectStore may use it to create
pipe/fifo.

To solve java issue realm/realm-java#4140
Part of #2411
beeender pushed a commit that referenced this issue Feb 13, 2017
@bmeike
Copy link
Contributor

bmeike commented Feb 14, 2017

The patch that will allow this test pass is being tracked in realm/realm-core#2445

@tmeunier
Copy link
Author

Good to know, thanks!

beeender added a commit to realm/realm-core that referenced this issue Feb 17, 2017
When compacting the Realm on external storage for Android, SharedGroup
always uses the default sys_tmp_dir which is invalid for Android. Thus
we need an API for setting the default sys_tmp_dir for bindings.
The getters is also required since ObjectStore may use it to create
pipe/fifo.

To solve java issue realm/realm-java#4140
Part of #2411
@beeender
Copy link
Contributor

beeender commented Feb 20, 2017

need core release v2.3.2

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

No branches or pull requests

5 participants