realm-core icon indicating copy to clipboard operation
realm-core copied to clipboard

Randomly crash when append objects to list in write transaction

Open marcuswu0814 opened this issue 3 years ago • 12 comments

SDK and version

SDK : RealmSwift Version: 10.28.1

Observations

  • How frequent do the crash occur? Random, but always if happened in specific device
  • Does it happen in production or during dev/test? Production
  • Can the crash be reproduced by you? No
  • Can you provide instructions for how we can reproduce it? Not sure, but in this case just append some object into list.

Crash log / stacktrace

MAIN THREAD - CRASHED

libsystem_kernel.dylib
__pthread_kill
libsystem_c.dylib
abort
Realm
please_report_this_issue_in_github_realm_realm_core
Realm
realm::util::terminate_internal(std::__1::basic_stringstream<char, std::__1::char_traits<char>, std::__1::allocator<char> >&)
Realm
realm::util::terminate(char const*, char const*, long, std::initializer_list<realm::util::Printable>&&)
Realm
void realm::util::terminate<unsigned long long, unsigned long long>(char const*, char const*, long, unsigned long long, unsigned long long) terminate.hpp:45
Realm
realm::ArraySmallBlobs::insert(unsigned long, realm::BinaryData, bool)
Realm
void realm::Cluster::do_insert_row<realm::ArrayString>(unsigned long, realm::ColKey, realm::Mixed, bool)
Realm
realm::util::FunctionRef<bool (realm::ColKey)>::FunctionRef<realm::Cluster::insert_row(unsigned long, realm::ObjKey, realm::FieldValues const&)::$_1&>(realm::Cluster::insert_row(unsigned long, realm::ObjKey, realm::FieldValues const&)::$_1&&&)::'lambda'(void*, realm::ColKey)::__invoke(void*, realm::ColKey)
Realm
realm::TableClusterTree::for_each_and_every_column(realm::util::FunctionRef<bool (realm::ColKey)>) const
Realm
realm::Cluster::insert_row(unsigned long, realm::ObjKey, realm::FieldValues const&)
Realm
realm::Cluster::insert(realm::ObjKey, realm::FieldValues const&, realm::ClusterNode::State&)
Realm
realm::ClusterNodeInner::insert(realm::ObjKey, realm::FieldValues const&, realm::ClusterNode::State&)::$_1::operator()(realm::ClusterNode*, realm::ClusterNodeInner::ChildInfo&) const
Realm
realm::ClusterNodeInner::insert(realm::ObjKey, realm::FieldValues const&, realm::ClusterNode::State&)
Realm
realm::ClusterTree::insert_fast(realm::ObjKey, realm::FieldValues const&, realm::ClusterNode::State&)
Realm
realm::ClusterTree::insert(realm::ObjKey, realm::FieldValues const&)
Realm
realm::TableClusterTree::insert(realm::ObjKey, realm::FieldValues const&)
Realm
realm::Table::create_object_with_primary_key(realm::Mixed const&, realm::FieldValues&&, realm::Table::UpdateMode, bool*)
Realm
realm::Table::create_object_with_primary_key(realm::Mixed const&, bool*) table.hpp:258
Realm
realm::Object realm::Object::create<objc_object* __strong, RLMAccessorContext>(RLMAccessorContext&, std::__1::shared_ptr<realm::Realm> const&, realm::ObjectSchema const&, objc_object* __strong, realm::CreatePolicy, realm::ObjKey, realm::Obj*) object_accessor.hpp:305
Realm
RLMAccessorContext::createObject(objc_object*, realm::CreatePolicy, bool, realm::ObjKey) RLMAccessor.mm:1102
Realm
realm::Obj RLMAccessorContext::unbox<realm::Obj>(objc_object*, realm::CreatePolicy, realm::ObjKey) RLMAccessor.mm:1134
Realm
auto realm::List::dispatch<void realm::List::insert<objc_object* const __strong&, RLMAccessorContext>(RLMAccessorContext&, unsigned long, objc_object* const __strong&&&, realm::CreatePolicy)::'lambda'(RLMAccessorContext&)>(objc_object* const __strong&) const list.hpp:212
Realm
void realm::List::insert<objc_object* const __strong&, RLMAccessorContext>(RLMAccessorContext&, unsigned long, objc_object* const __strong&&&, realm::CreatePolicy) list.hpp:211
Realm
___ZL15RLMInsertObjectP15RLMManagedArrayP11objc_objectm_block_invoke RLMManagedArray.mm:270
Realm
auto translateErrors<void () block_pointer __strong&>(void () block_pointer __strong&&&) RLMManagedArray.mm:181
Realm
changeArray(RLMManagedArray*, NSKeyValueChange, unsigned long, void () block_pointer) RLMManagedArray.mm:202
Realm
RLMInsertObject(RLMManagedArray*, objc_object*, unsigned long) RLMManagedArray.mm:268
Realm
-[RLMManagedArray addObject:] RLMManagedArray.mm:275
RealmSwift
RealmSwift.List.append(A) -> () List.swift:114

... My Production call stack, call `root.records.append(record)`

Steps & Code to Reproduce

In some device, just run:

let realm = try! Realm()
let root = findOrCreateRootObject() // create a custom root object
let record = RecordObject()

try! realm.write {
  root.account = currentAccount ?? ""
  root.records.append(record)
}

, and it happened

marcuswu0814 avatar Jul 28 '22 03:07 marcuswu0814

@marcuswu0814 How many instances have you seen with this exact stack trace? You have also just reported #5687 - have you seen a sudden increase in number of error reports and can you relate that to a recent upgrade to a newer Realm version?

jedelbo avatar Aug 01 '22 11:08 jedelbo

Did you mean how many Realm() instances I used in this thread?

marcuswu0814 avatar Aug 01 '22 11:08 marcuswu0814

Hi @jedelbo,

  1. The crash happen after update from 10.24.0 to 10.28.1.
  2. I'm not major in English, so can't sure what did you mean about first question, currently have 10 device (about 1%) facing the same crash with same stack trace. And the number is increasing.

If any missing info that I can provide, feel free to tell me, thanks.

marcuswu0814 avatar Aug 17 '22 08:08 marcuswu0814

Here is another crash stack trace, it crash at same file and line, but got different stack trace:

Thread 0 Crashed:
0   libsystem_platform.dylib             0x00000001da163ac4 _platform_memmove + 676
1   Realm                                0x0000000106b6ae88 void realm::Cluster::do_insert_row<realm::ArrayTimestamp>(unsigned long, realm::ColKey, realm::Mixed, bool) + 164
2   Realm                                0x0000000106b69e94 realm::util::FunctionRef<bool (realm::ColKey)>::FunctionRef<realm::Cluster::insert_row(unsigned long, realm::ObjKey, realm::FieldValues const&)::$_1&>(realm::Cluster::insert_row(unsigned long, realm::ObjKey, realm::FieldValues const&)::$_1&&&)::'lambda'(void*, realm::ColKey)::__invoke(void*, realm::ColKey) + 596
3   Realm                                0x0000000106c94aa8 realm::TableClusterTree::for_each_and_every_column(realm::util::FunctionRef<bool (realm::ColKey)>) const + 80
4   Realm                                0x0000000106b6545c realm::Cluster::insert_row(unsigned long, realm::ObjKey, realm::FieldValues const&) + 204
5   Realm                                0x0000000106b67444 realm::Cluster::insert(realm::ObjKey, realm::FieldValues const&, realm::ClusterNode::State&) + 236
6   Realm                                0x0000000106b77770 realm::ClusterNodeInner::insert(realm::ObjKey, realm::FieldValues const&, realm::ClusterNode::State&)::$_1::operator()(realm::ClusterNode*, realm::ClusterNodeInner::ChildInfo&) const + 68
7   Realm                                0x0000000106b729d0 realm::ClusterNodeInner::insert(realm::ObjKey, realm::FieldValues const&, realm::ClusterNode::State&) + 248
8   Realm                                0x0000000106b7622c realm::ClusterTree::insert_fast(realm::ObjKey, realm::FieldValues const&, realm::ClusterNode::State&) + 44
9   Realm                                0x0000000106b76494 realm::ClusterTree::insert(realm::ObjKey, realm::FieldValues const&) + 44
10  Realm                                0x0000000106c945ec realm::TableClusterTree::insert(realm::ObjKey, realm::FieldValues const&) + 48
11  Realm                                0x0000000106c8778c realm::Table::create_object_with_primary_key(realm::Mixed const&, realm::FieldValues&&, realm::Table::UpdateMode, bool*) + 868
12  Realm                                0x00000001069fe594 realm::Table::create_object_with_primary_key(realm::Mixed const&, bool*) (table.hpp:258)
13  Realm                                0x00000001069f3a04 realm::Object realm::Object::create<objc_object* __strong, RLMAccessorContext>(RLMAccessorContext&, std::__1::shared_ptr<realm::Realm> const&, realm::ObjectSchema const&, objc_object* __strong, realm::CreatePolicy, realm::ObjKey, realm::Obj*) (object_accessor.hpp:305)
14  Realm                                0x00000001069f33a4 RLMAccessorContext::createObject(objc_object*, realm::CreatePolicy, bool, realm::ObjKey) (RLMAccessor.mm:1102)
15  Realm                                0x00000001069f409c realm::Obj RLMAccessorContext::unbox<realm::Obj>(objc_object*, realm::CreatePolicy, realm::ObjKey) (RLMAccessor.mm:1134)
16  Realm                                0x0000000106a2d0f4 auto realm::List::dispatch<void realm::List::insert<objc_object* const __strong&, RLMAccessorContext>(RLMAccessorContext&, unsigned long, objc_object* const __strong&&&, realm::CreatePolicy)::'lambda'(RLMAccessorContext&)>(objc_object* const __strong&) const (list.hpp:212)
17  Realm                                0x0000000106a29784 void realm::List::insert<objc_object* const __strong&, RLMAccessorContext>(RLMAccessorContext&, unsigned long, objc_object* const __strong&&&, realm::CreatePolicy) (list.hpp:211)
18  Realm                                0x0000000106a2c500 ___ZL15RLMInsertObjectP15RLMManagedArrayP11objc_objectm_block_invoke (RLMManagedArray.mm:270)
19  Realm                                0x0000000106a2c544 auto translateErrors<void () block_pointer __strong&>(void () block_pointer __strong&&&) (RLMManagedArray.mm:181)
20  Realm                                0x0000000106a298f0 changeArray(RLMManagedArray*, NSKeyValueChange, unsigned long, void () block_pointer) (RLMManagedArray.mm:202)
21  Realm                                0x0000000106a29200 RLMInsertObject(RLMManagedArray*, objc_object*, unsigned long) (RLMManagedArray.mm:268)
22  Realm                                0x0000000106a29138 -[RLMManagedArray addObject:] (RLMManagedArray.mm:275)
23  RealmSwift                           0x000000010633a850 RealmSwift.List.append(A) -> () (List.swift:114)

marcuswu0814 avatar Aug 18 '22 07:08 marcuswu0814

@marcuswu0814 , what does the schema of the list you're inserting into look like? Is this a list of embedded objects? Do you have default values for some of columns of the object being inserted? It looks like from the two stacktraces there's a crash while populating a Timestamp field and/or a String/Binary field. When you say it happens "Random, but always if happened in specific device", do you mean that once it starts happening on that device it keeps happening on that device for the same kinds of objects or for all objects? If so, would you be willing to send a realm file where this problem is happening to us to try to reproduce the problem?

jbreams avatar Aug 18 '22 20:08 jbreams

Hi @jbreams, thanks for your help, the following code is my Realm Object (swift code):

Parent:


class UploadObject: Object {
    
    @Persisted(primaryKey: true) var id = ""
    
    @Persisted var account = ""
    
    @Persisted var date = Date()
    
    @Persisted var records: List<RecordObject>
    
}

Child:


extension RecordObject {
    
    enum State: String {
    
        case a, b, c
        
    }
    
}

class RecordObject: Object {
    
    @Persisted(primaryKey: true) var id = ""
    
    @Persisted var date = Date()
    
    @objc private dynamic var _state = State.a.rawValue
    // *NOTE

    @Persisted var jsonString = ""
    
    var state: State {
        get { State(rawValue: _state)! }
        set { _state = newValue.rawValue }
    }
    
}

*NOTE

After replace @objc with property wrapper refactoring, the line is missing and the field in db is not exist. I'm not sure if this mistake declare caused this bug, but I change this line to @Persisted private var _state = State.upload.rawValue now, but the new version not yet release.

Usage:

struct Logger {
            
    let myObject: MyObject
    
    func log(state: RecordObject.State) {
        let realm = try! Realm()
        let root = findOrCreateUploadObject()
        let record = RecordObject()
        let encoder = JSONEncoder()
        let json = try! encoder.encode(myObject)
        
        record.id = UUID().uuidString
        record.jsonString = String(data: json, encoding: .utf8)!
        record.state = state
        
        try! realm.write {
            root.account = UserSession.shared.currentLoginAccount ?? ""
            root.records.append(record)
        }
    }
    
    private func findOrCreateUploadObject() -> UploadObject {
        let realm = try! Realm()
        
        if realm.object(ofType: UploadObject.self, forPrimaryKey: myObject.id) == nil {
            let uploadObject = UploadObject()
            
            uploadObject.id = myObject.id
            
            try! realm.write {
                realm.add(uploadObject)
            }
        }
        
        return realm.object(ofType: UploadObject.self, forPrimaryKey: myObject.id)!
    }
    
}

Logger().log(state: .a) // run this

And for your question

, do you mean that once it starts happening on that device it keeps happening on that device for the same kinds of objects or for all objects...

I means when the crash occur, the db file will broken and the app will always crash when creating a Realm instance via let realm = try! Realm(), until remove and reinstall app.

We didn't have the broken *.realm file now, but we are working on this in next release. After that I can send you the file via mail.

marcuswu0814 avatar Aug 19 '22 08:08 marcuswu0814

➤ Finn Andersen commented:

Very fine. We are looking forward to receiving the file. Feel free to add any other relevant info if you come across any.

sync-by-unito[bot] avatar Aug 26 '22 14:08 sync-by-unito[bot]

Hi @jbreams, I got the broken realm file and it seems had wrong object key:

CleanShot 2022-09-05 at 15 14 44@2x

  • Open via Realm Studio

If you need the broken file, how do I send the file to you?

marcuswu0814 avatar Sep 05 '22 07:09 marcuswu0814

@marcuswu0814 you can send the file to [email protected]

jedelbo avatar Sep 05 '22 13:09 jedelbo

Hi @jedelbo, I sent the file yesterday. 🙏 Did you received that?

marcuswu0814 avatar Sep 07 '22 02:09 marcuswu0814

Hi @marcuswu0814 I had a look to the realm file you sent. I am a bit confused since I can't see neither UploadObject nor RecordObject among the classes listed in the realm file you sent. The database does not seem corrupted. Could a migration have broken your schema?

nicola-cab avatar Sep 07 '22 15:09 nicola-cab

@marcuswu0814 Sorry about the late reply. I had a look at the file too, and I found it to be somewhat inconsistent. We are not currently able to tell how it ended up like this, but having the file will hopefully help us to prevent it from happening in the future.

jedelbo avatar Sep 07 '22 15:09 jedelbo

Closed by #5993

jedelbo avatar Nov 17 '22 08:11 jedelbo

Can you please tell the realm-swift version to be used for fixing this error? @jedelbo

keerthika-priya avatar Nov 24 '22 08:11 keerthika-priya

v10.33.0 should contain the fix.

jedelbo avatar Dec 05 '22 09:12 jedelbo