I have a task that uses a CFRunLoopObserver like the following.
class Task {
CFRunLoopObserverRef fObserver;
public:
Task() {
CFRunLoopObserverContext context = {0, this, NULL, NULL, NULL};
fObserver = CFRunLoopObserverCreate(kCFAllocatorDefault,
kCFRunLoopBeforeWaiting,
true, 0, &MainRunLoopObserverCallback, &context);
::CFRunLoopAddObserver(CFRunLoopGetMain(), fObserver, kCFRunLoopCommonModes);
}
static void MainRunLoopObserverCallback(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) {
Task* task = reinterpret_cast<Task*>(info);
// task->member causes a crash if task deleted
}
~Task() {
if (fObserver)
{
::CFRunLoopRemoveObserver(CFRunLoopGetMain(), fObserver, kCFRunLoopCommonModes);
::CFRelease(fObserver);
}
}
};
I have noticed that the app crashes sometimes when the task object gets deleted before the CFRunLoopObserverCallBack is completed.
Would it be possible to make sure that the observer callback is complete before the observer is removed from the runloop?
The observers are always added an removed from the same thread.
That’s good.
Just for context, manipulating the run loop of thread A from thread B is supposed to work but my experience is that it opens you up to a bunch of problems, both in the OS and in your own code.
Coming back to your original issue, the key problem is this:
CFRunLoopObserverContext context = {0, this, NULL, NULL, NULL};
Your first two NULL
values are meant to be retain and release callbacks. The run loop uses those to ensure that the object referenced by the info
pointer (in your case that’s the C++ this
) sticks around until the run loop is done with it. By passing in NULL
you’re taking on the responsibility of ensuring that the object stays around until the run loop is done with it. That’s quite tricky.
The solution here is to use a reference-counted object and supply retain and release callbacks. This is pretty straightforward in Objective-C and Swift. I’m not familiar enough with reference counting in C++ to offer you advice on that front.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"