Alex Rivera | Logout

dealloc called on background GCD queue crashing app built with ARC

Asked 2012-01-19T18:14:13.407
10

I have a view controller that downloads an asset in a background GCD queue. I pass my downloading function a callback block to execute once the download is finished, and it always executes this block on the main thread.

The problem occurs if my view controller is dismissed by the user before the download is finished. I suspect what's happening is, once my view controller is dismissed, the callback block is the only thing retaining a strong reference to the controller. The callback block is only retained in a background thread, so once it's released, all the objects captured in the scope of the callback block are also released, albeit in a background queue.

This is the problem: being released in a background queue is causing dealloc to be run in that same queue, not the main queue. This, in turn, calls dealloc in the background and the app crashes:

2012-01-19 12:47:36.349 500px iOS[4892:12107] bool _WebTryThreadLock(bool), 0x306c10: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
[Switching to process 16643 thread 0x4103]
[Switching to process 16643 thread 0x4103]
(gdb) where
#0  0x307fd3c8 in _WebTryThreadLock ()
#1  0x307ff1b0 in WebThreadLock ()
#2  0x33f7865e in -[UITextView dealloc] ()
#3  0x0005d2ce in -[GCPlaceholderTextView dealloc] (self=0x309010, _cmd=0x340ce6b8) at /Users/ash/Dropbox/500px/500px-ios/500px iOS/500px iOS/GCPlaceholderTextView.m:113
#4  0x337cac42 in -[NSObject(NSObject) release] ()
#5  0x33dee5f4 in -[UIView(Hierarchy) removeFromSuperview] ()
#6  0x33e836cc in -[UIScrollView removeFromSuperview] ()
#7  0x33f762f0 in -[UITextView removeFromSuperview] ()
#8  0x33e01de2 in -[UIView dealloc] ()
#9  0x337cac42 in -[NSObject(NSObject) release] ()
#10 0x33dee5f4 in -[UIView(Hierarchy) removeFromSuperview] ()
#11 0x33e01de2 in -[UIView dealloc] ()
#12 0x33f437e4 in -[UIScrollView
Edit
Report

1 Answer

0

You can never guarantee that an object will be dealloced on any particular thread, as you have found out.

The best solution I have found is in your dealloc, check to see if you are on the main thread. If not, performSelector on the main thread with the rest of the dealloc and wait for completion.

Alternatively, implement that same logic with blocks: if not on he main thread, dispatch_sync to the main queue with the rest of the dealloc.

answered 2012-01-20T01:49:20.907

Your Answer