ASIHTTPRequest and NSOperationQueue crash on undo operations

I have a very difficult time trying to cancel queries in NSOperationQueue.

Before releasing my "engine" object, I call the cancelOperations method to cancel everything in the queue, so this will include ASIHTTPRequests flights and in the queue ... for example.

Engine.m

-(void)getContent { if (![self queue]) { [self setQueue:[[[NSOperationQueue alloc] init] autorelease]]; } NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setDelegate:self]; [request setDidFinishSelector:@selector(requestDone:)]; [[self queue] addOperation:request]; //queue is an NSOperationQueue } -(void)requestDone:(ASIHTTPRequest)*request { // Do something with request } -(void)cancelOperations { [self.queue cancelAllOperations]; [self.queue waitUntilAllOperationsAreFinished]; } -(void)dealloc { [super dealloc]; } 

Now, in my engine, I have several methods of type getContent, so my queue has different request objects in it. Stream when using the Engine object:

1) Open View Controller - view did load - alloc and init Engine object
2) // Call various getContent style methods to pause some operations
3) After exiting the window, call [engine cancelOperations]; to (a) stop any network requests in flight and also empty the queue
4) Cancel the view, and with this engine: [engine shutdown];

This works fine if all requests are completed in the queue (because they are empty), however, if I cancel the operation while the request is active, the application crashes with EXC_BAD_ACCESS error ... but AFTER the engine is successfully freed ...

Any ideas why this would be?

- EDIT-- Adding backtrace for error:

 Exception Type: EXC_BAD_ACCESS (SIGBUS) Exception Codes: KERN_PROTECTION_FAILURE at 0x00000000b0000000 Crashed Thread: 0 Dispatch queue: com.apple.main-thread Application Specific Information: objc_msgSend() selector name: respondsToSelector: iPhone Simulator 225, iPhone OS 4.1 (iPhone 4/8B117) Thread 0 Crashed: Dispatch queue: com.apple.main-thread 0 libobjc.A.dylib 0x02cb5907 objc_msgSend + 27 1 CoreFoundation 0x02ac95cd __invoking___ + 29 2 CoreFoundation 0x02ac94a1 -[NSInvocation invoke] + 145 3 Foundation 0x0015a3ca __NSThreadPerformPerform + 251 4 CoreFoundation 0x02b39faf __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 5 CoreFoundation 0x02a9839b __CFRunLoopDoSources0 + 571 6 CoreFoundation 0x02a97896 __CFRunLoopRun + 470 7 CoreFoundation 0x02a97350 CFRunLoopRunSpecific + 208 8 CoreFoundation 0x02a97271 CFRunLoopRunInMode + 97 9 GraphicsServices 0x0320c00c GSEventRunModal + 217 10 GraphicsServices 0x0320c0d1 GSEventRun + 115 11 UIKit 0x003e9af2 UIApplicationMain + 1160 12 Clicky 0x000027d4 main + 102 (main.m:14) 13 Clicky 0x00002765 start + 53 Thread 1: Dispatch queue: com.apple.libdispatch-manager 0 libSystem.B.dylib 0x97cfe942 kevent + 10 1 libSystem.B.dylib 0x97cff05c _dispatch_mgr_invoke + 215 2 libSystem.B.dylib 0x97cfe519 _dispatch_queue_invoke + 163 3 libSystem.B.dylib 0x97cfe2be _dispatch_worker_thread2 + 240 4 libSystem.B.dylib 0x97cfdd41 _pthread_wqthread + 390 5 libSystem.B.dylib 0x97cfdb86 start_wqthread + 30 Thread 2: 0 libSystem.B.dylib 0x97cfd9d2 __workq_kernreturn + 10 1 libSystem.B.dylib 0x97cfdf68 _pthread_wqthread + 941 2 libSystem.B.dylib 0x97cfdb86 start_wqthread + 30 Thread 3: WebThread 0 libSystem.B.dylib 0x97cd80fa mach_msg_trap + 10 1 libSystem.B.dylib 0x97cd8867 mach_msg + 68 2 CoreFoundation 0x02b3a436 __CFRunLoopServiceMachPort + 150 3 CoreFoundation 0x02a97984 __CFRunLoopRun + 708 4 CoreFoundation 0x02a97350 CFRunLoopRunSpecific + 208 5 CoreFoundation 0x02a97271 CFRunLoopRunInMode + 97 6 WebCore 0x034093a3 RunWebThread(void*) + 483 7 libSystem.B.dylib 0x97d0581d _pthread_start + 345 8 libSystem.B.dylib 0x97d056a2 thread_start + 34 Thread 4: 0 libSystem.B.dylib 0x97cfd9d2 __workq_kernreturn + 10 1 libSystem.B.dylib 0x97cfdf68 _pthread_wqthread + 941 2 libSystem.B.dylib 0x97cfdb86 start_wqthread + 30 Thread 5: 0 libSystem.B.dylib 0x97cd80fa mach_msg_trap + 10 1 libSystem.B.dylib 0x97cd8867 mach_msg + 68 2 CoreFoundation 0x02b3a436 __CFRunLoopServiceMachPort + 150 3 CoreFoundation 0x02a97984 __CFRunLoopRun + 708 4 CoreFoundation 0x02a97350 CFRunLoopRunSpecific + 208 5 CoreFoundation 0x02a9a614 CFRunLoopRun + 84 6 Clicky 0x0001fdb7 +[ASIHTTPRequest runRequests] + 167 (ASIHTTPRequest.m:4093) 7 Foundation 0x0014576c -[NSThread main] + 81 8 Foundation 0x001456f8 __NSThread__main__ + 1387 9 libSystem.B.dylib 0x97d0581d _pthread_start + 345 10 libSystem.B.dylib 0x97d056a2 thread_start + 34 Thread 6: 0 libSystem.B.dylib 0x97cd80fa mach_msg_trap + 10 1 libSystem.B.dylib 0x97cd8867 mach_msg + 68 2 CoreFoundation 0x02b3a436 __CFRunLoopServiceMachPort + 150 3 CoreFoundation 0x02a97984 __CFRunLoopRun + 708 4 CoreFoundation 0x02a97350 CFRunLoopRunSpecific + 208 5 CoreFoundation 0x02a97271 CFRunLoopRunInMode + 97 6 Foundation 0x0017ab86 +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:] + 398 7 Foundation 0x0014576c -[NSThread main] + 81 8 Foundation 0x001456f8 __NSThread__main__ + 1387 9 libSystem.B.dylib 0x97d0581d _pthread_start + 345 10 libSystem.B.dylib 0x97d056a2 thread_start + 34 Thread 7: 0 libSystem.B.dylib 0x97cf7086 select$DARWIN_EXTSN + 10 1 CoreFoundation 0x02acbb5e __CFSocketManager + 798 2 libSystem.B.dylib 0x97d0581d _pthread_start + 345 3 libSystem.B.dylib 0x97d056a2 thread_start + 34 Thread 8: 0 libSystem.B.dylib 0x97cfd9d2 __workq_kernreturn + 10 1 libSystem.B.dylib 0x97cfdf68 _pthread_wqthread + 941 2 libSystem.B.dylib 0x97cfdb86 start_wqthread + 30 Thread 0 crashed with X86 Thread State (32-bit): eax: 0x06641500 ebx: 0x000143f3 ecx: 0x0008e1c8 edx: 0x06606075 edi: 0xb0000000 esi: 0x066554c4 ebp: 0xbfffdef8 esp: 0xbfffdec4 ss: 0x0000001f efl: 0x00010206 eip: 0x02cb5907 cs: 0x00000017 ds: 0x0000001f es: 0x0000001f fs: 0x00000000 gs: 0x00000037 cr2: 0xb0000000 
+6
objective-c iphone nsoperationqueue
source share
4 answers

You do not release the operations queue in dealloc ...

One of the suspects is the delegation pattern:

[request setDelegate:self];

If the self object is destroyed, and the request is absent when the request is "completed", it will try to notify some garbage in memory, so the failure.

UPDATE: to fix this, add this code before canceling:

 for (ASIHTTPRequest *request in queue.operations) { [request setDelegate: nil]; [request setDidFinishSelector: nil]; } 
+4
source

I think jv42 is right about this reason. However, there is a handy helper for cleaning delegates ...

 -(void)dealloc { for (ASIHTTPRequest *request in queue.operations) { [request clearDelegatesAndCancel]; } [queue release]; [super dealloc]; } 

Has anyone found a faster method for this ... maybe one that doesn't include a request loop?

+4
source

Make sure you are using the recent ASIHTTPRequest version of git. v1.7 contains several race conditions that will cause failures when canceling requests.

0
source

I had the same situation when starting ASINetworkQueue with multiple queries.

I removed the dealloc exemption for the lineup and autoadvertising. Then I applied Leah's excellent suggestion to go through the zero delegates. Then I put the queue release on the queueRequestFinished delegate, and it solved my problem!

 bulkQueue = [[ASINetworkQueue alloc] init]; [bulkQueue setQueueDidFinishSelector:@selector(queueRequestFinished:)]; -(void)queueRequestFinished:(ASINetworkQueue *)queue { for (ASIHTTPRequest *request in queue.operations) { [request setDelegate: nil]; [request setDidFinishSelector: nil]; } } 

Hope this helps someone !:-)

0
source

All Articles