Realm in AsyncDisplayKit causes Termination - realm::IncorrectThreadException - ios

I'm using RealmSwift with AsyncDisplayKit, I'm getting this error all the time from ASDataController.mm:
libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.
I have a DataSourceManager class that contains the data, and a DatabaseManager that handles the fetch and insert operations.
Exception always occurs in _layoutNodesFromContexts:ofKind:completion:.
I've tried any combination of GCD that I knew (Serial, Concurrent, Barrier), but I couldn't handle this exception.
How should I manage this situation?
Thanks!

I've tried Unmanaged_RLMObject as workaround. Unmanaged_RLMObject is the RLMObject haven't add to RLMRealm.
It works, but I don't think it's good solution.
Unmanaged instances of RLMObjects behave exactly as regular NSObject
subclasses, and are safe to pass across threads.
Source

This is probably because AsyncDisplayKit (or Texture now) works on multiple background threads, and your realm objects are being passed around between threads. That's why the IncorrectThreadException.
To pass your realm objects between threads, use the ThreadSafeReference, along with using realm.resolve where you access your objects in AsyncDisplayKit.
More info here.

The quick and easy solution I have found is instead of accessing your data Model direct in they layoutSpecThatFits methods which are called in the background simply declare a parameter needed from the model and set it in your init method. Then use it in layoutSpecThatFits as usual.
For example:
Assume your data model is Person
class Person: Object {
#objc dynamic var name: String = ""
#objc dynamic var birthday: Date = Date()
}
In your node (CellNode, DisplayNode etc) on layoutSpecThatFit method don't access person direct instead have a property say name which you set it in init method, then use it like so: -
var name: String
init(person: Person){
// Set the property here so that you don't have to call person.name in layoutSpect method.
self.name = person.name
super.init()
}
override func layoutSpecThatFits(_ constrainedSize: ASSizeRange) -> ASLayoutSpec {
// Now you can safely use the param here on a different thread without issues.
if (self.name) {
// ---
}
}
Reference: I found the idea from this article

Related

Understanding Swift thread safety

I have encountered a data race in my app using Xcode's Thread Sanitizer and I have a question on how to address it.
I have a var defined as:
var myDict = [Double : [Date:[String:Any]]]()
I have a thread setup where I call a setup() function:
let queue = DispatchQueue(label: "my-queue", qos: .utility)
queue.async {
self.setup {
}
}
My setup() function essentially loops through tons of data and populates myDict. This can take a while, which is why we need to do it asynchronously.
On the main thread, my UI accesses myDict to display its data. In a cellForRow: method:
if !myDict.keys.contains(someObject) {
//Do something
}
And that is where I get my data race alert and the subsequent crash.
Exception NSException * "-[_NSCoreDataTaggedObjectID objectForKey:]:
unrecognized selector sent to instance
0x8000000000000000" 0x0000000283df6a60
Please kindly help me understand how to access a variable in a thread safe manner in Swift. I feel like I'm possibly half way there with setting, but I'm confused on how to approach getting on the main thread.
One way to access it asynchronously:
typealias Dict = [Double : [Date:[String:Any]]]
var myDict = Dict()
func getMyDict(f: #escaping (Dict) -> ()) {
queue.async {
DispatchQueue.main.async {
f(myDict)
}
}
}
getMyDict { dict in
assert(Thread.isMainThread)
}
Making the assumption, that queue possibly schedules long lasting closures.
How it works?
You can only access myDict from within queue. In the above function, myDict will be accessed on this queue, and a copy of it gets imported to the main queue. While you are showing the copy of myDict in a UI, you can simultaneously mutate the original myDict. "Copy on write" semantics on Dictionary ensures that copies are cheap.
You can call getMyDict from any thread and it will always call the closure on the main thread (in this implementation).
Caveat:
getMyDict is an async function. Which shouldn't be a caveat at all nowadays, but I just want to emphasise this ;)
Alternatives:
Swift Combine. Make myDict a published Value from some Publisher which implements your logic.
later, you may also consider to use async & await when it is available.
Preface: This will be a pretty long non-answer. I don't actually know what's wrong with your code, but I can share the things I do know that can help you troubleshoot it, and learn some interesting things along the way.
Understanding the error
Exception NSException * "-[_NSCoreDataTaggedObjectID objectForKey:]: unrecognized selector sent to instance 0x8000000000000000"
An Objective C exception was thrown (and not caught).
The exception happened when attempting to invoke -[_NSCoreDataTaggedObjectID objectForKey:]. This is a conventional way to refer to an Objective C method in writing. In this case, it's:
An instance method (hence the -, rather than a + that would be used for class methods)
On the class _NSCoreDataTaggedObjectID (more on this later)
On the method named objectForKey:
The object receiving this method invocation is the one with address 0x8000000000000000.
This is a pretty weird address. Something is up.
Another hint is the strange class name of _NSCoreDataTaggedObjectID. There's a few observations we can make about it:
The prefixed _NS suggests that it's an internal implementation detail of CoreData.
We google the name to find class dumps of the CoreData framework, which show us that:
_NSCoreDataTaggedObjectID subclasses _NSScalarObjectID
Which subclasses _NSCoreManagedObjectID
Which subclasses NSManagedObjectID
NSManagedObjectID is a public API, which has its own first-party documentation.
It has the word "tagged" in its name, which has a special meaning in the Objective C world.
Some back story
Objective C used message passing as its sole mechanism for method dispatch (unlike Swift which usually prefers static and v-table dispatch, depending on the context). Every method call you wrote was essentially syntactic sugar overtop of objc_msgSend (and its variants), passing to it the receiver object, the selector (the "name" of the method being invoked) and the arguments. This was a special function that would do the job of checking the class of the receiver object, and looking through that classes' hierarchy until it found a method implementation for the desired selector.
This was great, because it allows you to do a lot of cool runtime dynamic behaviour. For example, menu bar items on a macOS app would just define the method name they invoke. Clicking on them would "send that message" to the responder chain, which would invoke that method on the first object that had an implementation for it (the lingo is "the first object that answers to that message").
This works really well, but has several trade-offs. One of them was that everything had to be an object. And by object, we mean a heap-allocated memory region, whose first several words of memory stored meta-data for the object. This meta-data would contain a pointer to the class of the object, which was necessary for doing the method-loopup process in objc_msgSend as I just described.
The issue is, that for small objects, (particularly NSNumber values, small strings, empty arrays, etc.) the overhead of these several words of object meta-data might be several times bigger than the actual object data you're interested in. E.g. even though NSNumber(value: true /* or false */) stores a single bit of "useful" data, on 64 bit systems there would be 128 bits of object overhead. Add to that all the malloc/free and retain/release overhead associated with dealing with large numbers of tiny object, and you got a real performance issue.
"Tagged pointers" were a solution to this problem. The idea is that for small enough values of particular privileged classes, we won't allocate heap memory for their objects. Instead, we'll store their objects' data directly in their pointer representation. Of course, we would need a way to know if a given pointer is a real pointer (that points to a real heap-allocated object), or a "fake pointer" that encodes data inline.
The key realization that malloc only ever returns memory aligned to 16-byte boundaries. This means that 4 bits of every memory address were always 0 (if they weren't, then it wouldn't have been 16-byte aligned). These "unused" 4 bits could be employed to discriminate real pointers from tagged pointers. Exactly which bits are used and how differs between process architectures and runtime versions, but the general idea is the same.
If a pointer value had 0000 for those 4 bits then the system would know it's a real object pointer that points to a real heap-allocated object. All other possible values of those 4-bit values could be used to signal what kind of data is stored in the remaining bits. The Objective C runtime is actually opensource, so you can actually see the tagged pointer classes and their tags:
{
// 60-bit payloads
OBJC_TAG_NSAtom = 0,
OBJC_TAG_1 = 1,
OBJC_TAG_NSString = 2,
OBJC_TAG_NSNumber = 3,
OBJC_TAG_NSIndexPath = 4,
OBJC_TAG_NSManagedObjectID = 5,
OBJC_TAG_NSDate = 6,
// 60-bit reserved
OBJC_TAG_RESERVED_7 = 7,
// 52-bit payloads
OBJC_TAG_Photos_1 = 8,
OBJC_TAG_Photos_2 = 9,
OBJC_TAG_Photos_3 = 10,
OBJC_TAG_Photos_4 = 11,
OBJC_TAG_XPC_1 = 12,
OBJC_TAG_XPC_2 = 13,
OBJC_TAG_XPC_3 = 14,
OBJC_TAG_XPC_4 = 15,
OBJC_TAG_NSColor = 16,
OBJC_TAG_UIColor = 17,
OBJC_TAG_CGColor = 18,
OBJC_TAG_NSIndexSet = 19,
OBJC_TAG_NSMethodSignature = 20,
OBJC_TAG_UTTypeRecord = 21,
// When using the split tagged pointer representation
// (OBJC_SPLIT_TAGGED_POINTERS), this is the first tag where
// the tag and payload are unobfuscated. All tags from here to
// OBJC_TAG_Last52BitPayload are unobfuscated. The shared cache
// builder is able to construct these as long as the low bit is
// not set (i.e. even-numbered tags).
OBJC_TAG_FirstUnobfuscatedSplitTag = 136, // 128 + 8, first ext tag with high bit set
OBJC_TAG_Constant_CFString = 136,
OBJC_TAG_First60BitPayload = 0,
OBJC_TAG_Last60BitPayload = 6,
OBJC_TAG_First52BitPayload = 8,
OBJC_TAG_Last52BitPayload = 263,
OBJC_TAG_RESERVED_264 = 264
You can see, strings, index paths, dates, and other similar "small and numerous" classes all have reserved pointer tag values. For each of these "normal classes" (NSString, NSDate, NSNumber, etc.), there's a special internal subclass which implements all the same public API, but using a tagged pointer instead of a regular object.
As you can see, there's a value for OBJC_TAG_NSManagedObjectID. It turns out, that NSManagedObjectID objects were numerous and small enough that they would benefit greatly for this tagged-pointer representation. After all, the value of NSManagedObjectID might be a single integer, much like NSNumber, which would be wasteful to heap-allocate.
If you'd like to learn more about tagged pointers, I'd recommend Mike Ash's writings, such as https://www.mikeash.com/pyblog/friday-qa-2012-07-27-lets-build-tagged-pointers.html
There was also a recent WWDC talk on the subject: WWDC 2020 - Advancements in the Objective-C runtime
The strange address
So in the previous section we found out that _NSCoreDataTaggedObjectID is the tagged-pointer subclass of NSManagedObjectID. Now we can notice something else that's strange, the pointer value we saw had a lot of zeros: 0x8000000000000000. So what we're dealing with is probably some kind of uninitialized-state of an object.
Conclusion
The call stack can shed further light on where this happens exactly, but what we know is that somewhere in your program, the objectForKey: method is being invoked on an uninitialized value of NSManagedObjectID.
You're probably accessing a value too-early, before it's properly initialized.
To work around this you can take one of several approaches:
A future ideal world, use would just use the structured concurrency of Swift 5.5 (once that's available on enough devices) and async/await to push the work on the background and await the result.
Use a completion handler to invoke your value-consuming code only after the value is ready. This is most immediately-easy, but will blow up your code base with completion handler boilerplate and bugs.
Use a concurrency abstraction library, like Combine, RxSwift, or PromiseKit. This will be a bit more work to set up, but usually leads to much clearer/safer code than throwing completion handlers in everywhere.
The basic pattern to achieve thread safety is to never mutate/access the same property from multiple threads at the same time. The simplest solution is to just never let any background queue interact with your property directly. So, create a local variable that the background queue will use, and then dispatch the updating of the property to the main queue.
Personally, I wouldn't have setup interact with myDict at all, but rather return the result via the completion handler, e.g.
// properties
var myDict = ...
private let queue = DispatchQueue(label: "my-queue", qos: .utility) // some background queue on which we'll recalculate what will eventually be used to update `myProperty`
// method doesn't reference `myDict` at all, but uses local var only
func setup(completion: #escaping (Foo) -> Void) {
queue.async {
var results = ... // some local variable that we'll use as we're building up our results
// do time-consuming population of `results` here;
// do not touch `myDict` here, though;
// when all done, dispatch update of `myDict` back to the main queue
DispatchQueue.main.async { // dispatch update of property back to the main queue
completion(results)
}
}
}
Then the routine that calls setup can update the property (and trigger necessary UI update, too).
setup { results in
self.myDict = results
// also trigger UI update here, too
}
(Note, your closure parameter type (Foo in my example) would be whatever type myDict is. Maybe a typealias as advised elsewhere, or better, use custom types rather than dictionary within dictionary within dictionary. Use whatever type you’d prefer.)
By the way, your question’s title and preamble talks about TSAN and thread safety, but you then share a “unrecognized selector” exception, which is a completely different issue. So, you may well have two completely separate issues going on. A TSAN data race error would have produced a very different message. (Something like the error I show here.) Now, if setup is mutating myDict from a background thread, that undoubtedly will lead to thread-safety problems, but your reported exception suggests there might also be some other problem, too...

Any way to detect `UnsafeMutablePointer` has been deallocated?

I got a custom observer which is checking if changes have been made to objects it is observing. The object holds reference to the original property (pointer) in an UnsafeMutablePointer ... the problem is that all works jolly good unless the original value deallocates and I start getting random values from whatever now occupies that bit of memory ...
Is there any way to detect the original object is gone so I can invalidate my observer?
Edit: To make clear what I am trying to achieve I have added my current implementation (which kinda works for local class variables):
class Observer<Observed> where Observed: Equatable {
typealias Binder = ((Observed) -> ())
typealias Storage = UnsafeMutablePointer<Observed>
private var storage: Storage
private var bind: Binder
private var running: Bool
init(_ value: Storage, binder: #escaping Binder) {
storage = value
bind = binder
running = true
var val: Observed = value.pointee
DispatchQueue.global().async {
while self.running {
if val != value.pointee {
self.bind(value.pointee)
val = value.pointee
}
}
}
}
var value: Observed {
return storage.pointee
}
deinit {
running = false
}
}
No; it is your responsibility to ensure that an unsafe pointer cannot outlive its referenced object. ("Important memory details are your problem" is what Swift generally means by the "Unsafe" designation.)
Generally the correct tool here is a weak reference rather than a pointer.
Your observation code is incorrect in numerous ways. The basic approach of a tight loop that reads the value and compares it to an existing value is going to drain battery very quickly even if it had no other problems. It's also invalid because your pointee isn't thread-safe. You can't read it on a random thread and be promised a coherent value.
Swift doesn't promise that value types stay at the same place in memory, so even if the value still "exists," your pointer is not promised to point to it. It doesn't even promise that value types have a heap (i.e. persistent) memory location; they may be stored on the stack or even in registers. When you take a pointer to it, it may create a temporary copy in order to provide a memory location, but it's not promised to be the same memory as other references to it. That's the whole point of a value type. It can be freely copied and moved around (and even entirely optimized away in some cases). If you need to be able to refer to the instance, then you need a reference type.

iOS Swift5 will using NSMutableDictionary with locks instead of var [:] ensure thread safety?

I'm debugging a swift class that I have inherited in a project. There was an attempt to create a thread safe dictionary using a swift dictionary with a semaphore. The code fails in multi threaded environment - the swift dictionary is treated as a struct and is copied on mutation, regardless of the semaphore.
I'm trying to understand: Will replacing a swift struct based dictionary with a core foundation NSMutableDictionary (with a semaphore) ensure thread safety of the code?
I see this answer for Objective-C, but my question is about modifying the swift code.
public class ThreadSafeDictionary<KeyType: Hashable, ValueType> {
private var dictionary: [KeyType: ValueType] = [:]
//change to:
private let dictionary = NSMutableDictionary() //will this make the mutating code thread safe?
public func add(key: KeyType, value: ValueType) {
// semaphore wait
// set value in dictionary
// semaphore signal
}
}
Or - is there a way to use swift keywords like mutating or inout to make sure that the semaphores would prevent multiple threads from each working with a copy of a swift dictionary?
Updated: there was a bug in a higher level code, creating 2 independent instances of ThreadSafeDictionary. Fixing that resolved the concurrency issue.
If you wrap a Swift directory (e.g. struct,) into a Swift class (a reference type), you will somehow lose the copy-on-write-mechanism of the struct (which indeed is intended to prevent multi threading issues). Therefore you will not gain anything if you change the inner directory member from a Swift type to Foundation's NSMutableDirectory. Also, mutating or inout do not imply any thread safety.
To make ThreadSafeDictionary thread safe, you need to wrap all the access methods of the inner directory, as you depicted in the func add...() function. Instead of using semaphores, you could also use GCD with your own serial queue.

Realm accessed from incorrect thread - again

I noticed many problems with accessing realm object, and I thought that my solution would be solving that.
So I have written simple helping method like this:
public func write(completion: #escaping (Realm) -> ()) {
DispatchQueue(label: "realm").async {
if let realm = try? Realm() {
try? realm.write {
completion(realm)
}
}
}
}
I thought that completion block will be fine, because everytime I write object or update it, I use this method above.
Unfortunately I'm getting error:
libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.
Instances of Realm and Object are thread-contained. They cannot be passed between threads or that exception will occur.
Since you're passing the completion block itself to the background queue at the same time the queue is being created (As Dave Weston said), any Realm objects inside that block will most certainly not have been created on the same thread, which would explain this error.
Like Dave said, you're creating a new dispatch queue every time you call that method. But to expand upon that, there's also no guarantee by iOS that a single queue will be consistently called on the same thread.
As such, best practice with Realm is to recreate your Realm objects on the same thread each time you want to perform a new operation on that thread. Realm internally caches instances of Realm on a per-thread basis, so there's very little overhead involved with calling Realm() multiple times.
To update a specific object, you can use the new ThreadSafeReference feature to re-access the same object on a background thread.
let realm = try! Realm()
let person = Person(name: "Jane") // no primary key required
try! realm.write {
realm.add(person)
}
let personRef = ThreadSafeReference(to: person)
DispatchQueue(label: "com.example.myApp.bg").async {
let realm = try! Realm()
guard let person = realm.resolve(personRef) else {
return // person was deleted
}
try! realm.write {
person.name = "Jane Doe"
}
}
Your method creates a new DispatchQueue every time you call it.
DispatchQueue(name:"") is an initializer, not a lookup. If you want to make sure you're always on the same queue, you'll need to store a reference to that queue and dispatch to it.
You should create the queue when you setup the Realm, and store it as a property of the class that does the setup.
Perhaps it helps someone (as I spent a few hours looking for a solution)
In my case, I had a crash in background mapping of JSON to a model (which imported ObjectMapper_Realm). At the same time there was an instance of realm allocated on main thread.
Generally it happens when you initialised it in different thread and trying to access or modify from different thread. Just put a debugger to see which thread it was initialised and try to use same thread.

Why is weak_table_t a member of SideTable in Objective-C runtime?

I am reading code of objc from https://github.com/opensource-apple/objc4.
In the code, there is a struct SideTable, which contains reference count of corresponding object and a weak_table_t.
struct SideTable {
spinlock_t slock;
RefcountMap refcnts;
weak_table_t weak_table;
SideTable() {
memset(&weak_table, 0, sizeof(weak_table));
}
~SideTable() {
_objc_fatal("Do not delete SideTable.");
}
void lock() { slock.lock(); }
void unlock() { slock.unlock(); }
bool trylock() { return slock.trylock(); }
// Address-ordered lock discipline for a pair of side tables.
template<bool HaveOld, bool HaveNew>
static void lockTwo(SideTable *lock1, SideTable *lock2);
template<bool HaveOld, bool HaveNew>
static void unlockTwo(SideTable *lock1, SideTable *lock2);
};
And the SideTable of an object can be retrieved by SideTables()[obj] as the SideTable of every object is stored in a StripedMap, which is actually an array using the hash value of an object's address as index.
But according to the code of weak_entry_for_referent, the runtime gets the weak_entry_t of a referent through checking weak_table->weak_entries[index].referent.
static weak_entry_t *
weak_entry_for_referent(weak_table_t *weak_table, objc_object *referent)
{
assert(referent);
weak_entry_t *weak_entries = weak_table->weak_entries;
if (!weak_entries) return nil;
size_t index = hash_pointer(referent) & weak_table->mask;
size_t hash_displacement = 0;
while (weak_table->weak_entries[index].referent != referent) {
index = (index+1) & weak_table->mask;
hash_displacement++;
if (hash_displacement > weak_table->max_hash_displacement) {
return nil;
}
}
return &weak_table->weak_entries[index];
}
It means the weak_table contains more than the weak entries for a single object. Then why is weak_table_t a member of SideTable instead of a global data?
As I can't find code which really initialize SideTable of object (storeStrong just use the SideTable without initializing it at first) and weak_table, I can't quite understand how things work in the background.
Can anybody give me a hint?
why is weak_table_t a member of SideTable
There are two cases should be solved if use a global weak_table_t.(refcnts has the same cases)
case 1: Maintaining the weak_table_t should be thread safe, so we need lock
case 2: lock means slow, but the developer want the system run as fast as possible
Only one global weak_table_t can't solved the two cases above.
Actuactly, class StripedMap solves the two cases by using lock striping, by wrapping weak_table_t and refcnts together inside SideTable.
Let's take a look at the code below, copied from objc-private.h.
// StripedMap<T> is a map of void* -> T, sized appropriately
// for cache-friendly lock striping.
// For example, this may be used as StripedMap<spinlock_t>
// or as StripedMap<SomeStruct> where SomeStruct stores a spin lock.
template<typename T>
class StripedMap {
// ... code for StripedMap
PaddedT array[StripeCount]; // There are 8 SideTables if define TARGET_OS_IPHONE
// ... code for StripedMap
}
8 SideTables store 8 weak_table_t and 8 spinlock_t slock. The system can maintain 8 weak_table_t cocurrently at most for 8 thread.
I think this is fast enought on a iOS device.
SideTable init
SideTablesMap.init(); called from arr_init().
You can use "Find Call Hierarchy" on init of class ExplicitInit to find the call hierarchy
The only reasonable reason I can figure out is:
The SideTableBuf for all SideTable instances is actually a bucket array. Different objects may be put in the same bucket. So a single SideTable may serve for different pointers according to the hash algorithm. And then, the weak_table actually contains weak_entry_t for different referents. That's why we need check the referent by:
while (weak_table->weak_entries[index].referent != referent)
And the weak_table serves for the current SideTable only, so it can't be a global data.
Weak table is a shared resource which allows access from multiple threads. Thus, we need a lock to avoid data inconsistency. So weak_table_t is wrapped in SideTable along with spinlock_t.
However, it's inefficient to have the whole table locked for each access. Considering the case, Thread A has acquired the lock, and is modifying the weak table. Meanwhile, Thread B wants to modify the weak table, so it tries to acquire the lock. However, only one thread can own the lock at a time. So Thread B blocks. If this happens all the time, access to weak table would be very slow.
Then developers came up with the pattern, "Lock Striping", dividing the table into multiple buckets, each of which can be locked independently. Upon that modifying bucket 1 doesn't block the modifying of bucket 2. So SideTable is wrapped in StripedMap for partition purpose.

Resources