-
Type: Bug
-
Resolution: Fixed
-
Priority: Unknown
-
None
-
Affects Version/s: None
-
Component/s: None
We get a strange crash in Realm on iOS when our App is brought into foreground sometimes. Most of the time there is no problem. The function we use is very straight forward, and is called very often without any issue.
static func getContestLastSyncVersion(contestId: String) -> Single<Int> { return Single.deferred { let realm = try Realm.tryCreate() // next line will crash on very rare occasions let items = realm.objects(CacheContest.self).filter("id == %@", contestId) return Single.just(items.first?.contestMessages.max(ofProperty: "syncVersion") ?? 0) } }
The stack trace suggests that the crash happens in _platform_memcmp called by realm::Group::do_get_table. Our Code is labeled "Hanako" in the stack trace.
MAIN THREAD - CRASHED libsystem_platform.dylib _platform_memcmp Realm realm::Group::do_get_table(realm::StringData, bool (*)(realm::Spec const&)) Realm realm::ObjectStore::table_for_object_type(realm::Group&, realm::StringData) group.hpp:939 Realm (anonymous namespace)::get_table(realm::Group&, RLMObjectSchema*) RLMQueryUtil.mm:206 Realm RLMPredicateToQuery(NSPredicate*, RLMObjectSchema*, RLMSchema*, realm::Group&) RLMQueryUtil.mm:1474 Realm -[RLMResults objectsWithPredicate:] RLMResults.mm:361 RealmSwift function signature specialization <Arg[0] = Exploded> of RealmSwift.Results.filter(Swift.String, Any...) -> RealmSwift.Results<A> Results.swift:211 Hanako closure #1 () throws -> RxSwift.PrimitiveSequence<RxSwift.SingleTrait, Swift.Int> in static Hanako.ContestCacheImpl.getContestLastSyncVersion(contestId: Swift.String) -> RxSwift.PrimitiveSequence<RxSwift.SingleTrait, Swift.Int> ContestCacheImpl.swift:220 Hanako partial apply forwarder for closure #1 () throws -> RxSwift.PrimitiveSequence<RxSwift.SingleTrait, Swift.Int> in static Hanako.ContestCacheImpl.getContestLastSyncVersion(contestId: Swift.String) -> RxSwift.PrimitiveSequence<RxSwift.SingleTrait, Swift.Int> <compiler-generated>:0 RxSwift partial apply forwarder for closure #1 () throws -> RxSwift.Observable<B> in static RxSwift.PrimitiveSequence.deferred(() throws -> RxSwift.PrimitiveSequence<A, B>) -> RxSwift.PrimitiveSequence<A, B> PrimitiveSequence.swift:69 RxSwift partial apply forwarder for reabstraction thunk helper <A where A: RxSwift.ObservableType> from @escaping @callee_guaranteed () -> (@owned RxSwift.Observable<A.E>, @error @owned Swift.Error) to @escaping @callee_guaranteed () -> (@out RxSwift.Observable<A.E>, @error @owned Swift.Error) <compiler-generated>:0 RxSwift RxSwift.(DeferredSink in _9A640CB28D6420293D75F113534DFAC6).run() -> RxSwift.Disposable Deferred.swift:36 RxSwift RxSwift.(Deferred in _9A640CB28D6420293D75F113534DFAC6).run<A where A1: RxSwift.ObserverType, A.E == A1.E>(_: A1, cancel: RxSwift.Cancelable) -> (sink: RxSwift.Disposable, subscription: RxSwift.Disposable) Deferred.swift:71 RxSwift RxSwift.Producer.subscribe<A where A == A1.E, A1: RxSwift.ObserverType>(A1) -> RxSwift.Disposable Producer.swift:18 RxSwift RxSwift.(MergeSink in _DDEA0423368B3B462AE46699A4D080E1).run(RxSwift.Observable<A>) -> RxSwift.Disposable Merge.swift:507 RxSwift merged RxSwift.(FlatMap in _DDEA0423368B3B462AE46699A4D080E1).run<A where A1: RxSwift.ObserverType, B.E == A1.E>(_: A1, cancel: RxSwift.Cancelable) -> (sink: RxSwift.Disposable, subscription: RxSwift.Disposable) RxSwift closure #1 (()) -> RxSwift.Disposable in RxSwift.Producer.subscribe<A where A == A1.E, A1: RxSwift.ObserverType>(A1) -> RxSwift.Disposable Producer.swift:26 RxSwift function signature specialization <Arg[2] = [Closure Propagated : reabstraction thunk helper from @escaping @callee_guaranteed () -> (@out RxSwift.Disposable) to @escaping @callee_guaranteed (@in_guaranteed ()) -> (@out RxSwift.Disposable), Argument Types : [@escaping @callee_guaranteed () -> (@out RxSwift.Disposable)]> of generic specialization <()> of RxSwift.CurrentThreadScheduler.schedule<A>(_: A, action: (A) -> RxSwift.Disposable) -> RxSwift.Disposable <compiler-generated>:0 RxSwift RxSwift.Producer.subscribe<A where A == A1.E, A1: RxSwift.ObserverType>(A1) -> RxSwift.Disposable Producer.swift:24 RxSwift (extension in RxSwift): RxSwift.ObservableType.subscribe((RxSwift.Event<A.E>) -> ()) -> RxSwift.Disposable ObservableType+Extensions.swift:25 Hanako closure #1 (RxSwift.Event<Swift.Int>) -> () in Hanako.ContestChatViewModel.refreshMessages(tableView: __C.UITableView?) -> () ContestChatViewModel.swift:133 Hanako reabstraction thunk helper from @escaping @callee_guaranteed (@guaranteed RxSwift.Event<Swift.Int>) -> () to @escaping @callee_guaranteed (@in_guaranteed RxSwift.Event<Swift.Int>) -> () <compiler-generated>:0 RxSwift partial apply forwarder for closure #1 (RxSwift.Event<A.E>) -> () in (extension in RxSwift):RxSwift.ObservableType.subscribe((RxSwift.Event<A.E>) -> ()) -> RxSwift.Disposable ObservableType+Extensions.swift:23 RxSwift RxSwift.AnonymousObserver.onCore(RxSwift.Event<A>) -> () AnonymousObserver.swift:24 RxSwift RxSwift.ObserverBase.on(RxSwift.Event<A>) -> () ObserverBase.swift:18 RxSwift protocol witness for RxSwift.ObserverType.on(RxSwift.Event<A.E>) -> () in conformance RxSwift.ObserverBase<A> : RxSwift.ObserverType in RxSwift <compiler-generated>:0 RxSwift RxSwift.Sink.forwardOn(RxSwift.Event<A.E>) -> () Sink.swift:34 RxSwift closure #1 (A.E) -> A.E in RxSwift.(TimerSink in _92B4E76F25CED73665C45EB7986E9847).run() -> RxSwift.Disposable Timer.swift:66 RxSwift closure #2 () -> () in RxSwift.DispatchQueueConfiguration.schedulePeriodic<A>(_: A, startAfter: Swift.Double, period: Swift.Double, action: (A) -> A) -> RxSwift.Disposable DispatchQueueConfiguration.swift:98 RxSwift reabstraction thunk helper from @escaping @callee_guaranteed () -> () to @escaping @callee_unowned @convention(block) () -> () <compiler-generated>:0
The crash also happens in the very same location but is triggered from another function in our Code. Stack Trace during crash is just the same (above calling this function).
static func getDate(_ key: String, defValue: Date = Date()) -> Date { guard let realm = try? Realm.tryCreate(), // next line will also crash on very rare occasions let item = realm.object(ofType: CacheDateValue.self, forPrimaryKey: key) else { return defValue } return item.value }
These functions have in common: they are called from a timer (see second last line in the stack trace):
let timer = DispatchSource.makeTimerSource(queue: self.queue) timer.schedule(deadline: initial, repeating: dispatchInterval(period), leeway: self.leeway) timer.setEventHandler(handler: { if cancelTimer.isDisposed { return } timerState = action(timerState) })
Versions used:
Installing Realm (3.21.0) Installing RealmSwift (3.21.0) Installing RxRealm (0.7.6) Installing RxSwift (4.5.0)