SHORT STORY

I discovered a bug in my app today caused by the following repeatable behavior: 
 When one particular NSInvocationOperation in an NSOperationQueue executes, two 
others get whacked out of the queue, and thus never execute.

LONG STORY

Starting with an empty NSOperationQueue, which I have subclassed, I add 40 
operations.  Each operation is added as a dependency of the next operation, so 
that they will execute sequentially. 

All but three of the operations are instances of my own subclass of 
NSOperation.  Indexed starting with 1, these operations, numbers 17, 32 and 40, 
are NSInvocationOperations.  Although all three of the subject invocations 
invoke the same target (which happens to be the operation queue) and the same 
selector, the three invocations are different objects, and the three invocation 
operations are different objects.

I am observing the queue's 'operations' using key-value observing; my observer 
runs whenever an operation is dequeued.

During the execution of operation 17, my observer runs, and upon debugging I 
see that this is because operations 32 and 40, which were there during the 
previous run, have been somehow whacked out of the queue!  Higher-indexed 
operations have slid up to fill in the resulting gaps.  During this time, the 
method invoked by these operations' invocations has executed only once, for 
operation 17.  My observer runs again a few milliseconds later, as expected, 
when Operation 17 completes and is dequeued.  The call stack under the observer 
during the double whack indicates that the perpetrator is a secondary thread 
executing code from the bowels of Grand Central Dispatch…

Thread-16-<com.apple.root.default-overcommit-priority>
#0      0x00103f90 in -[SSYOperationQueue 
observeValueForKeyPath:ofObject:change:context:] at SSYOperationQueue.m:252
#1      0x92ce98b4 in NSKeyValueNotifyObserver
#2      0x92ccf95d in -[NSObject(NSKeyValueObservingPrivate) 
_changeValueForKey:key:key:usingBlock:]
#3      0x92ccf525 in -[NSObject(NSKeyValueObservingPrivate) 
_changeValueForKey:usingBlock:]
#4      0x92cfd44d in __NSOQDelayedFinishOperations
#5      0x99de0344 in _dispatch_after_timer_callback
#6      0x99de2cc2 in _dispatch_source_invoke
#7      0x99ddf6be in _dispatch_queue_invoke
#8      0x99ddeeb8 in _dispatch_worker_thread2
#9      0x9629db24 in _pthread_wqthread
#10     0x9629f6fe in start_wqthread

Fortunately, NSInvocationOperation is only a convenience, and by simply 
replacing these operations with instances of my own NSOperation subclass, the 
problem was fixed.

Can anyone take a stab at explaining this?  On one hand, I don't see how my 
code could be doing this, because there is no API for removing operations.  But 
on the other hand, there is not likely to be such a heinous bug in Lion.  App 
is built using the 10.6 SDK.  I did not test the errant build in 10.6, because 
spending a half day on this wasn't in my schedule :|

Jerry Krinock

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to