Simperium / simperium-ios

Simperium libraries and samples
MIT License
206 stars 43 forks source link

Attempted to remove unregistered weak referrer #264

Closed dsmurfin closed 10 years ago

dsmurfin commented 10 years ago

I'm not sure if this is something I'm doing which is unusual, but I'm getting the following error when reloading a table view with cells using an SPManagedObject class.

Attempted to remove unregistered weak referrer

The trace shows SPManagedObject .cxx_destruct

I've found this post which looks like it may be the issue I'm encountering, but I'm not sure how I could resolve it myself using an SPManagedObject.

http://lists.apple.com/archives/cocoa-dev/2012/Apr/msg00071.html

Thanks as ever.

jleandroperez commented 10 years ago

Hello @dsmurfin,

I've not seen a crash like this one before. SPManagedObject is essentially a NSManagedObject subclass, so in theory you could try implementing the workaround mentioned in the link you've provided.

May i ask you which OS you're testing, and its version? (iOS / OSX)

Are you replicating the exact same conditions as mentioned in that post? (killing the MOC while the NSManagedObject's are still alive?). Are you resetting the MOC in one thread, while the MO is still being accessed in another thread?

IMHO, perhaps a more healthy way to prevent this (if that's indeed the scenario that triggers it), is by just stopping anything you're doing before resetting / killing the MOC.

dsmurfin commented 10 years ago

Hi @jleandroperez

This a cross platform app, but I'm currently building out the OS X 10.9 side. I could easily test the same scenario on iOS though with a bit of work.

Interestingly I'm not actually resetting the MOC myself. When it occurs, I update an array which is the datasource for an NSTableView and then call a reload. The error occurs for every instance of the SPManagedObject which existed before the array is refreshed.

jleandroperez commented 10 years ago

@dsmurfin would it be possible to post the entire stack trace?

(By the way, whenever possible, take a look at NSArrayController, that class should help you nuke a lot of glue code!)

dsmurfin commented 10 years ago

@jleandroperez absolutely. As soon as I'm back at that machine I'll get it over to you.

Good shout, thanks for that...!

jleandroperez commented 10 years ago

@dsmurfin no problem!. NSArrayController should help you "replicate" NSFetchedResultsController's behavior, by wiring NSTableView with the MOC (and that should, also, auto-refresh the table when new data arrives).

Thank you!

dsmurfin commented 10 years ago

@jleandroperez here's the full trace:

Interestingly I added a new table view and array controller and switched off all of the original code and the same thing occurred with that also.

Thread 1, Queue : com.apple.main-thread

0 0x00007fff8f8efe07 in weak_unregister_no_lock ()

1 0x00007fff8f8f057e in objc_destroyWeak_slow(objcobject*) ()

2 0x00000001000750c0 in -[SPManagedObject .cxx_destruct] at /Users/Daniel/Dropbox/Work/Lighting and Stage/Jobs and Projects/iOS Development/ShowTool Spot/ShowTool Spot/Pods/Simperium/Simperium/SPManagedObject.m:21

3 0x00007fff8f8e0afb in object_cxxDestructFromClass(objcobject, objc_class*) ()

4 0x00007fff8f8db002 in objc_destructInstance ()

5 0x00007fff8fb93f8e in _PFPerformDebugZombie ()

6 0x00007fff8fb276ce in -[_PFManagedObjectReferenceQueue _processReferenceQueue:]()

7 0x00007fff8fb0650c in _performRunLoopAction ()

8 0x00007fff8b5dae17 in CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION ()

9 0x00007fff8b5dad87 in __CFRunLoopDoObservers ()

10 0x00007fff8b5cbf44 in CFRunLoopRunSpecific ()

11 0x00007fff8dfe5a0d in RunCurrentEventLoopInMode ()

12 0x00007fff8dfe5685 in ReceiveNextEventCommon ()

13 0x00007fff8dfe55bc in _BlockUntilNextEventMatchingListInModeWithFilter ()

14 0x00007fff944b13de in _DPSNextEvent ()

15 0x00007fff944b0a2b in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]()

16 0x00007fff944a4b2c in -[NSApplication run]()

17 0x00007fff9448f913 in NSApplicationMain ()

18 0x0000000100023db2 in main at /Users/Daniel/Dropbox/Work/Lighting and Stage/Jobs and Projects/iOS Development/ShowTool Spot/ShowTool Spot/ShowTool Spot/ShowTool-Spot-OSX/main.m:13

Thread 2, Queue : (null) Thread 3, Queue : com.apple.libdispatch-manager Thread 4, Queue : (null) Thread 5, Queue : (null) Thread 6, Queue : (null) Thread 7, Queue : (null)

jleandroperez commented 10 years ago

@dsmurfin

Hey there. I've been trying to replicate this crash, and so far i've not been able. Would you please describe the scenario that triggers this?.

Just for the sake of testing this, would you please toggle the 'weak' reference to SPBucket into strong? (SPManagedObject.h).

dsmurfin commented 10 years ago

@jleandroperez

Ok, so changing to strong I can't make it crash. All the other references to this error I've found on google were related to GC (which obviously I'm not using) but it looks like maybe it's being released to early for some reason.

It's not a hugely complicated scenario, but I've simplified it slightly:

2 x NSTableView 2 x NSArray (strong) - data source for table views

  1. Initialise view, array 1 populated using fetch request.
  2. Row 0 selected by default on tableview 1
  3. Array 2 populated using relationship to selected object in array 1
  4. Select table view 1 row 1 (user)
  5. Update array 2
  6. Reload table view 2
  7. All delegate methods complete successfully
  8. Crash

Cheers

Dan

jleandroperez commented 10 years ago

@dsmurfin Under normal circumstances, SPBucket objects are never dealloc'ed. Not even after a signout.

May i ask you to please add a breakpoint into Simperium's dealloc method? Just in case, to make sure the entire object is not getting nuked. That might explain this behavior!

Thanks!

dsmurfin commented 10 years ago

@jleandroperez makes sense.

I've just done that and it's not hitting dealloc, it always just stops on SPManagedObject.

I'd be happy to zip up this project and send it over to you if that's a help, bearing in mind it's very much early development!!

Cheers

jleandroperez commented 10 years ago

@dsmurfin it'd be awesome if you could just isolate a sample of the entire code, just enough to replicate the crash.

You can mail me here: jorge.perez [at] automattic [dot] com

Thank you!

jleandroperez commented 10 years ago

Daniel,

I’ve noticed something odd: the app will only crash if Zombies are enabled. In fact, the source seems to be PFPerformDebugZombie.

Thread 1, Queue : com.apple.main-thread
#0 0x00007fff8f8efe07 in weak_unregister_no_lock ()
#1 0x00007fff8f8f057e in objc_destroyWeak_slow(objc_object**) ()
#2 0x00000001000750c0 in -[SPManagedObject .cxx_destruct] at /Users/Daniel/Dropbox/Work/Lighting and Stage/Jobs and Projects/iOS Development/ShowTool Spot/ShowTool Spot/Pods/Simperium/Simperium/SPManagedObject.m:21
#3 0x00007fff8f8e0afb in object_cxxDestructFromClass(objc_object*, objc_class*) ()
#4 0x00007fff8f8db002 in objc_destructInstance ()
#5 0x00007fff8fb93f8e in PFPerformDebugZombie ()

The message says:

objc[81983]: attempted to remove unregistered weak referrer 0x1f60a6fd8

I've been trying to unsuccessfully spot the object it's being referred to. It's not a SPBucket instance, and there's definitely nothing weird being done, just a simple reload.

Would you please confirm if this still breaks with Zombies disabled? thank you!

dsmurfin commented 10 years ago

@jleandroperez thank you so much. That had me baffled.

Turning off Zombies makes the problem go away. I've never seen anything like that before and I always test with Zombies so that's intriguing. Sounds like one to submit to Apple.

jleandroperez commented 10 years ago

@dsmurfin on the contrary, thanks for reporting this!

The worst part is: there is no SPBucket instance getting dealloc'ed anywhere. It seems to be just the SPManagedObject instance getting released.

If you submit to Apple's Radar, please, let us know if you hear anything back from them.

Thank you!!