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

NoSuchTable thrown from import_copy_of() #3761

Closed
finnschiermer opened this issue Jun 4, 2020 · 7 comments · Fixed by #4234
Closed

NoSuchTable thrown from import_copy_of() #3761

finnschiermer opened this issue Jun 4, 2020 · 7 comments · Fixed by #4234
Assignees

Comments

@finnschiermer
Copy link
Contributor

finnschiermer commented Jun 4, 2020

This was originally reported in issue #3701, but it's a different error.

Copy of original report (by @ironage ):

Stack trace:

Starting test testCreateMultipleEmbeddedObjects
uncaught exception in notifier thread: N5realm11NoSuchTableE: No such table exists
Exception backtrace:
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(_ZNK5realm13ConstTableRef5checkEv+0x78) [0x7fc38d854188]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(_ZNK5realm13ConstTableRefptEv+0x9) [0x7fc38d8541d9]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(_ZN5realm11Transaction14import_copy_ofENS_13ConstTableRefE+0x19) [0x7fc38d7bf869]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(_ZN5realm5QueryC2EPKS0_PNS_11TransactionENS_13PayloadPolicyE+0x170) [0x7fc38d65b0c0]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(_ZN5realm11Transaction14import_copy_ofERNS_5QueryENS_13PayloadPolicyE+0x32) [0x7fc38d7bfde2]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(+0x409db8) [0x7fc38d353db8]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(+0x3f0542) [0x7fc38d33a542]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(+0x404963) [0x7fc38d34e963]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(+0x405275) [0x7fc38d34f275]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(+0x41b16c) [0x7fc38d36516c]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(+0x41b210) [0x7fc38d365210]
/mnt/jenkins/workspace/realm_realm-js_PR-2901/compiled/node-v64_linux_x64/realm.node(+0xb91ce0) [0x7fc38dadbce0]
/lib64/libpthread.so.0(+0x7ea5) [0x7fc3909acea5]
/lib64/libc.so.6(clone+0x6d) [0x7fc3906d58dd]
terminate called after throwing an instance of 'realm::NoSuchTable'
  what():  No such table exists

Code:

testCreateMultipleEmbeddedObjects: function() {
        const realm = new Realm({schema: [schemas.HouseOwnerSchema, schemas.AddressSchema]});

        realm.write(() => {
            realm.create(schemas.HouseOwnerSchema.name, { name: "Ib", addresses: [
                { street: "Algade", city: "Nordby" },
                { street: "Skolevej", city: "Sydpynten" }
            ]});
            realm.create(schemas.HouseOwnerSchema.name, { name: "Petra", addresses: [
                { street: "Algade", city: "Nordby" }
            ]});
            realm.create(schemas.HouseOwnerSchema.name, { name: "Hans" });
        });

        let owners = realm.objects(schemas.HouseOwnerSchema.name).sorted("name");
        let addresses = realm.objects(schemas.AddressSchema.name).sorted("street");
        TestCase.assertEqual(owners.length, 3);
        TestCase.assertEqual(addresses.length, 3);

        const names = ["Hans", "Ib", "Petra"];
        for (let i = 0; i < names.length; i++) {
            TestCase.assertEqual(owners[i]["name"], names[i]);
        }

        let streets = ["Algade", "Algade", "Skolevej"];
        for (let i = 0; i < streets.length; i++) {
            TestCase.assertEqual(addresses[i]["street"], streets[i]);
        }

        realm.write(() => {
            addresses[0]["street"] = "Strandvejen";
        });

        streets = ["Algade", "Skolevej", "Strandvejen"];
        for (let i = 0; i < streets.length; i++) {
            TestCase.assertEqual(addresses[i]["street"], streets[i]);
        }

        realm.close();
    }
@finnschiermer
Copy link
Contributor Author

The call stack indicates an attempt to "handover" a table from transaction A to B but at a point in time, where A is no longer valid.

@finnschiermer
Copy link
Contributor Author

Since it happens on the notifier thread, one may speculate if perhaps high CPU load has delayed the thread in which we want to import to a point where the stuff we want to import is no longer valid. If so, this would point to a bug in either OS or JS violating the constraints for use of "import_copy_of".

@finnschiermer
Copy link
Contributor Author

Cannot reproduce. Closing, presumed fixed by #3749.

@finnschiermer
Copy link
Contributor Author

@tgoyne
Copy link
Member

tgoyne commented Dec 17, 2020

I think I may have spotted what could be causing this.

@finnschiermer
Copy link
Contributor Author

finnschiermer commented Dec 17, 2020

Awesome! Waiting anxiously.

@tgoyne
Copy link
Member

tgoyne commented Dec 17, 2020

When a new ResultsNotifier is created, it copies the query from the source Results to the notifier Transaction on the worker thread without any locking involved. This is actually almost safe, but there's a TOCTOU race at https://github.com/realm/realm-core/blob/master/src/realm/object-store/impl/results_notifier.cpp#L219 and we'll hit this error if the source Realm is invalidated between the check and when we obtain the table key inside import_copy_of(). The timing required for this is very tight, which explains why it's a pretty rare crash.

The code currently is still very structured around both the idea that creating a SharedGroup is an expensive operation and having explicit handover objects. It seems pretty easy to fix this and simplify the code a little by adjusting it to better take advantage of how things work now.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants