iOS app crashes on resuming - objective-c

(SEE UPDATE AT THE BOTTOM)
Recently I've started getting a weird and rare crash of my iPhone app when it returns from background. The crash log consists of system calls only:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000138
Crashed Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libobjc.A.dylib 0x34c715b0 objc_msgSend + 16
1 CoreFoundation 0x368b7034 _CFXNotificationPost + 1424
2 Foundation 0x34379d8c -[NSNotificationCenter postNotificationName:object:userInfo:] + 68
3 UIKit 0x37ddfec2 -[UIApplication _handleApplicationResumeEvent:] + 1290
4 UIKit 0x37c37d5c -[UIApplication handleEvent:withNewEvent:] + 1288
5 UIKit 0x37c376d0 -[UIApplication sendEvent:] + 68
6 UIKit 0x37c3711e _UIApplicationHandleEvent + 6150
7 GraphicsServices 0x36dea5a0 _PurpleEventCallback + 588
8 CoreFoundation 0x3693b680 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12
9 CoreFoundation 0x3693aee4 __CFRunLoopDoSources0 + 208
10 CoreFoundation 0x36939cb2 __CFRunLoopRun + 642
11 CoreFoundation 0x368aceb8 CFRunLoopRunSpecific + 352
12 CoreFoundation 0x368acd44 CFRunLoopRunInMode + 100
13 GraphicsServices 0x36de92e6 GSEventRunModal + 70
14 UIKit 0x37c8b2fc UIApplicationMain + 1116
15 [MyAppName] 0x00083d60 main (main.m:20)
16 [MyAppName] 0x00080304 start + 36
This might look like a zombie object being called on UIApplicationWillEnterForegroundNotification or UIApplicationDidBecomeActiveNotification (guessing by _handleApplicationResumeEvent in stack trace and the time when it crashes), but:
None of my classes register for UIApplicationDidBecomeActiveNotification, and only a couple of singletons (that stay alive forever) register for UIApplicationWillEnterForegroundNotification;
I've done some experimenting, and it turns out that posting UIApplicationWillEnterForegroundNotification goes from [UIApplication _sendWillEnterForegroundCallbacks:], and it isn't in the crash log.
For me, all this implies a bug in some library I'm using, or a system bug, and the crash occurred once on iOS 5.1.1 (release build), once on iOS 6.0 (release build) and once on iOS 6.0 (debug build). I scanned every library I'm using and have access to the source code for, and they aren't registering for neither UIApplicationWillEnterForegroundNotification nor UIApplicationDidBecomeActiveNotification. The only library I don't have access to is TestFlight, but the crash occurred on both 1.0 and 1.1 versions of TestFlight, and I've been using the former for quite a while now, without such problems.
So, summing up, I have no idea why has this crash come up and what's it coming from. Any ideas?
UPDATE 1
I've investigated the issue a bit deeper, thanks to DarthMike and matt for their help. By using notification center callback and logging stack trace, I've discovered that this exact stack comes up when and only when UIApplicationResumedNotification notification is fired as a part of returning from background. And guess what - it's some "private" notification and it doesn't have a public identifier counterpart. It doesn't have userInfo and its object is UIApplication (as many other notifications that are posted before this). Obviously I don't use it, neither does any library I have source code for. I can't even find any reasonable mentioning of it in the Internet! I also highly doubt that TestFlight is the culprit, because crash happened during debug too, and I don't "take off" TestFlight in debug mode.
Here's the stack trace for receiving UIApplicationResumedNotification. The offsets are all the same but with a constant byte offset (2 or 4, depending on the library - probably because it's a debug stack tracing, not release):
0 [MyAppName] 0x0016f509 NotificationsCallback + 72
1 CoreFoundation 0x3598ce25 __CFNotificationCenterAddObserver_block_invoke_0 + 124
2 CoreFoundation 0x35911037 _CFXNotificationPost + 1426
3 Foundation 0x333d3d91 -[NSNotificationCenter postNotificationName:object:userInfo:] + 72
4 UIKit 0x36e39ec7 -[UIApplication _handleApplicationResumeEvent:] + 1294
5 UIKit 0x36c91d61 -[UIApplication handleEvent:withNewEvent:] + 1292
6 UIKit 0x36c916d5 -[UIApplication sendEvent:] + 72
7 UIKit 0x36c91123 _UIApplicationHandleEvent + 6154
8 GraphicsServices 0x35e445a3 _PurpleEventCallback + 590
9 CoreFoundation 0x35995683 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14
10 CoreFoundation 0x35994ee9 __CFRunLoopDoSources0 + 212
11 CoreFoundation 0x35993cb7 __CFRunLoopRun + 646
12 CoreFoundation 0x35906ebd CFRunLoopRunSpecific + 356
13 CoreFoundation 0x35906d49 CFRunLoopRunInMode + 104
14 GraphicsServices 0x35e432eb GSEventRunModal + 74
15 UIKit 0x36ce5301 UIApplicationMain + 1120
16 [MyAppName] 0x000aa603 main + 390
17 [MyAppName] 0x000a41b0 start + 40
NotificationsCallback is an "observer" callback I've added for debug just for now.
Just to prove a point, I've deliberately omitted a removeObserver: call from one of my objects to generate a zombie/exception, and stack trace still included _CFXNotificationPost + 1426 followed by a crash with EXC_BAD_ACCESS in objc_msgSend + 16, just as in my original crash.
So this just means that someone has registered an observer for UIApplicationResumedNotification and haven't removed it before the observer was deallocated. Based on the fact that I never registered for such a notification, I can assume that this crash is not my fault. Still the question remains - whose it is then? I wonder who actually registers for this notification anyway...
UPDATE 2
While I'm still waiting to see if there are any changes with this bug on the new version of my app, I've got another crash on the previous version caused by this. Turns out that whatever registers for UIApplicationResumedNotification, specifies selector _applicationResuming: for it. I doubt that's of any use though.

I had exactly the same stack trace in a crash report from a device running IOS 6.0.1. I managed to reproduce the problem on Simulator through the following pattern:
Put the application in the background
Simulate a memory warning from simulator menu
Bring the application back to the foreground
After a lot of debugging I discovered that the _applicationResuming: message is sent to a UITextField which I am releasing as a reaction to Memory Warning. I tested the same pattern under IOS 5.1 but it didn't cause a crash. For some reason in IOS 6 UITextField registers for ApplicationResumeEvent (maybe not always but after the keyboard has appeared).
My workaround was to remove this object from NSNotificationCenter before releasing it:
[[NSNotificationCenter defaultCenter] removeObserver:self.placeFld];
self.placeFld = nil;

I just ran into this issue and found a solution that did not involve removing notifications. In our case, there was old code that was doing this:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
[searchBar resignFirstResponder];
// other stuff
}
I do not know why we had this, but it is gone now and the crash is gone. It appears that in this case, resigning first responder while searchBarTextDidBeginEditing is being called orphans a notification on the search bar's text edit field, and then we'd crash as soon as the view controller owning this UISearchBar was deallocated and we did the background / foreground dance.
YMMV

Put a breakpoint on -[NSNotificationCenter postNotificationName:object:userInfo:]. It's trying to send a notification to an object that isn't there any more, or something like that. You may be mismanaging your own notifications or your own objects.
Consider switching to ARC if you are not using it already.
Use the static analyzer. It can find potential memory issues.

Could be many things, but I think checking in code who registers for ANY UIApplication notification would be better. You don't really know which notification triggers the error.
Also, is any object retaining/holding strong reference on the AppDelegate? It may cause some weird retain cycle making this crash happen.
I've never seen such a crash by XCode misbehaviour.
EDIT: Pasting all notifications from header file. may be overkill but some could be sent on app resume/from background
UIKIT_EXTERN NSString *const UIApplicationDidEnterBackgroundNotification NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSString *const UIApplicationWillEnterForegroundNotification NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSString *const UIApplicationDidFinishLaunchingNotification;
UIKIT_EXTERN NSString *const UIApplicationDidBecomeActiveNotification;
UIKIT_EXTERN NSString *const UIApplicationWillResignActiveNotification;
UIKIT_EXTERN NSString *const UIApplicationDidReceiveMemoryWarningNotification;
UIKIT_EXTERN NSString *const UIApplicationWillTerminateNotification;
UIKIT_EXTERN NSString *const UIApplicationSignificantTimeChangeNotification;
UIKIT_EXTERN NSString *const UIApplicationWillChangeStatusBarOrientationNotification; // userInfo contains NSNumber with new orientation
UIKIT_EXTERN NSString *const UIApplicationDidChangeStatusBarOrientationNotification; // userInfo contains NSNumber with old orientation
UIKIT_EXTERN NSString *const UIApplicationStatusBarOrientationUserInfoKey; // userInfo dictionary key for status bar orientation
UIKIT_EXTERN NSString *const UIApplicationWillChangeStatusBarFrameNotification; // userInfo contains NSValue with new frame
UIKIT_EXTERN NSString *const UIApplicationDidChangeStatusBarFrameNotification; // userInfo contains NSValue with old frame
UIKIT_EXTERN NSString *const UIApplicationStatusBarFrameUserInfoKey; // userInfo dictionary key for status bar frame
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsURLKey NS_AVAILABLE_IOS(3_0); // userInfo contains NSURL with launch URL
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsSourceApplicationKey NS_AVAILABLE_IOS(3_0); // userInfo contains NSString with launch app bundle ID
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsRemoteNotificationKey NS_AVAILABLE_IOS(3_0); // userInfo contains NSDictionary with payload
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsLocalNotificationKey NS_AVAILABLE_IOS(4_0); // userInfo contains a UILocalNotification
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsAnnotationKey NS_AVAILABLE_IOS(3_2); // userInfo contains object with annotation property list
UIKIT_EXTERN NSString *const UIApplicationProtectedDataWillBecomeUnavailable NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSString *const UIApplicationProtectedDataDidBecomeAvailable NS_AVAILABLE_IOS(4_0);
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsLocationKey NS_AVAILABLE_IOS(4_0); // app was launched in response to a CoreLocation event.
UIKIT_EXTERN NSString *const UIApplicationLaunchOptionsNewsstandDownloadsKey NS_AVAILABLE_IOS(5_0); // userInfo contains an NSArray of NKAssetDownlo

A few things I do to clear the deck before debugging something an odd crash.
Build Clean (gets rid of local cached files).
Delete the app from Simulator / Device (sometimes XIBs are cached).
Re launch Xcode (there are some weird bugs when Xcode isn't in sync with the current setup).
Then, try again.

Related

NSSavePanel crash in sandbox app OS X 10.10

I'm using the NSSavePanel in OS X 10.10 in a sandboxed app to let the user choose the save location of a file (pretty standard), however the app crashes when i call:
NSSavePanel *panel = [NSSavePanel savePanel];
I get this in the debugger:
2014-10-14 18:22:16.019 Farm Hand[2807:942766] an error occurred while attempting to connect to listener 'com.apple.view-bridge': Connection interrupted
2014-10-14 18:22:16.020 Farm Hand[2807:942766] *** Assertion failure in +[NSXPCSharedListener connectionForListenerNamed:fromServiceNamed:], /SourceCache/ViewBridge/ViewBridge-99/NSXPCSharedListener.m:394
2014-10-14 18:22:16.023 Farm Hand[2807:942766] An uncaught exception was raised
2014-10-14 18:22:16.023 Farm Hand[2807:942766] NSXPCSharedListener unable to create endpoint for listener named com.apple.view-bridge
2014-10-14 18:22:16.023 Farm Hand[2807:942766] (
0 CoreFoundation 0x00007fff8880364c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff9390e6de objc_exception_throw + 43
2 CoreFoundation 0x00007fff8880342a +[NSException raise:format:arguments:] + 106
3 Foundation 0x00007fff8a3a65b9 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
4 ViewBridge 0x00007fff964e40b8 +[NSXPCSharedListener connectionForListenerNamed:fromServiceNamed:] + 151
5 ViewBridge 0x00007fff964c2981 -[NSRemoteViewBase serviceMarshalConnection] + 286
6 ViewBridge 0x00007fff964c36ae -[NSRemoteViewBase advanceToConfigPhase:awaitingWindowRights:] + 414
7 ViewBridge 0x00007fff964d1f7b -[NSWindowCentricRemoteView advanceToConfigPhase] + 947
8 ViewBridge 0x00007fff964c4223 -[NSRemoteViewBase viewServiceMarshalProxy:withErrorHandler:] + 88
9 ViewBridge 0x00007fff964ba8a8 -[NSRemoteViewBase bridge] + 207
10 AppKit 0x00007fff8e859b9d -[NSVBSavePanel init] + 303
11 AppKit 0x00007fff8e5a8ec1 +[NSSavePanel newRemotePanel] + 301
12 AppKit 0x00007fff8e5a8f53 +[NSSavePanel _crunchyRawUnbonedPanel] + 74
13 Farm Hand 0x000000010009526d __40-[RHFlockHomeViewController exportTable]_block_invoke_3 + 109
14 libdispatch.dylib 0x00000001002202bb _dispatch_call_block_and_release + 12
15 libdispatch.dylib 0x000000010021ad43 _dispatch_client_callout + 8
16 libdispatch.dylib 0x0000000100229d9f _dispatch_main_queue_callback_4CF + 1370
17 CoreFoundation 0x00007fff88756c59 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
18 CoreFoundation 0x00007fff887132ef __CFRunLoopRun + 2159
19 CoreFoundation 0x00007fff88712838 CFRunLoopRunSpecific + 296
20 HIToolbox 0x00007fff94ec743f RunCurrentEventLoopInMode + 235
21 HIToolbox 0x00007fff94ec71ba ReceiveNextEventCommon + 431
22 HIToolbox 0x00007fff94ec6ffb _BlockUntilNextEventMatchingListInModeWithFilter + 71
23 AppKit 0x00007fff8e006821 _DPSNextEvent + 964
24 AppKit 0x00007fff8e005fd0 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 194
25 AppKit 0x00007fff8dff9f73 -[NSApplication run] + 594
26 AppKit 0x00007fff8dfe5424 NSApplicationMain + 1832
27 Farm Hand 0x0000000100010552 main + 34
28 libdyld.dylib 0x00007fff8d7e85c9 start + 1
)
2014-10-14 18:22:16.027 Farm Hand[2807:942766] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSXPCSharedListener unable to create endpoint for listener named com.apple.view-bridge'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff8880364c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff9390e6de objc_exception_throw + 43
2 CoreFoundation 0x00007fff8880342a +[NSException raise:format:arguments:] + 106
3 Foundation 0x00007fff8a3a65b9 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 195
4 ViewBridge 0x00007fff964e40b8 +[NSXPCSharedListener connectionForListenerNamed:fromServiceNamed:] + 151
5 ViewBridge 0x00007fff964c2981 -[NSRemoteViewBase serviceMarshalConnection] + 286
6 ViewBridge 0x00007fff964c36ae -[NSRemoteViewBase advanceToConfigPhase:awaitingWindowRights:] + 414
7 ViewBridge 0x00007fff964d1f7b -[NSWindowCentricRemoteView advanceToConfigPhase] + 947
8 ViewBridge 0x00007fff964c4223 -[NSRemoteViewBase viewServiceMarshalProxy:withErrorHandler:] + 88
9 ViewBridge 0x00007fff964ba8a8 -[NSRemoteViewBase bridge] + 207
10 AppKit 0x00007fff8e859b9d -[NSVBSavePanel init] + 303
11 AppKit 0x00007fff8e5a8ec1 +[NSSavePanel newRemotePanel] + 301
12 AppKit 0x00007fff8e5a8f53 +[NSSavePanel _crunchyRawUnbonedPanel] + 74
13 Farm Hand 0x000000010009526d __40-[RHFlockHomeViewController exportTable]_block_invoke_3 + 109
14 libdispatch.dylib 0x00000001002202bb _dispatch_call_block_and_release + 12
15 libdispatch.dylib 0x000000010021ad43 _dispatch_client_callout + 8
16 libdispatch.dylib 0x0000000100229d9f _dispatch_main_queue_callback_4CF + 1370
17 CoreFoundation 0x00007fff88756c59 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
18 CoreFoundation 0x00007fff887132ef __CFRunLoopRun + 2159
19 CoreFoundation 0x00007fff88712838 CFRunLoopRunSpecific + 296
20 HIToolbox 0x00007fff94ec743f RunCurrentEventLoopInMode + 235
21 HIToolbox 0x00007fff94ec71ba ReceiveNextEventCommon + 431
22 HIToolbox 0x00007fff94ec6ffb _BlockUntilNextEventMatchingListInModeWithFilter + 71
23 AppKit 0x00007fff8e006821 _DPSNextEvent + 964
24 AppKit 0x00007fff8e005fd0 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 194
25 AppKit 0x00007fff8dff9f73 -[NSApplication run] + 594
26 AppKit 0x00007fff8dfe5424 NSApplicationMain + 1832
27 Farm Hand 0x0000000100010552 main + 34
28 libdyld.dylib 0x00007fff8d7e85c9 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
This is my code in full:
if ([format isEqualToString:#".csv"]) {
loadingBar = [RHLoadingBar loadingBarWithMessage:#"Preparing File..."];
[loadingBar showModally];
[loadingBar start];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *string = [[RHFileController sharedController] CSVTableWithObject:sheepArrayController.arrangedObjects propertyKeys:#[#"tagNumber", #"ukNumber", #"age", #"breed", #"comments"] columnHeaders:#[#"Tag Number", #"UK Number", #"Age", #"Breed", #"Comments"]];
dispatch_async(dispatch_get_main_queue(), ^{
[loadingBar stop];
[loadingBar dismiss];
NSSavePanel *panel = [NSSavePanel savePanel];
[panel beginSheetModalForWindow:[[NSApplication sharedApplication] mainWindow] completionHandler:^(NSInteger result) {
}];
});
});
}
Is this a known bug or is it something in my code? If it's a known bug can I get round it.
EDIT: This is how I'm getting around it until Apple fix it (thank's to #serren for the fix):
First uncheck the Is Initial Controller in your primary window controller (your App won't automatically launch the main window now).
Then:
In the AppDelegate.h:
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
// Add strong reference to the root window controller
#property (strong) NSWindowController *rootController;
#end
Finally in AppDelegate.m implement applicationDidFinishLaunching: like so (remember to set your initial controller identifier, here mine is "HomeView"):
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
// Show main window (to avoid powerbox bug)...
NSStoryboard *sb = [NSStoryboard storyboardWithName:#"Main" bundle:nil];
rootController = [sb instantiateControllerWithIdentifier:#"HomeView"];
[rootController showWindow:self];
// Other custom setup for your App...
}
This process will mean that the NSApplication's mainWindow property will be set to the rootController.window automatically. So if you want to get your main window at any time you can still call [[NSApplication sharedApplication] mainWindow]; Also the AppDelegate and the NSApplication singleton both have a strong reference to this window which is important (otherwise the window will be released and the App will crash).
Hope this helps for the time being.
Unfortunately the answer above had nothing to do with my scenario, as there were no ArrayControllers present on the screen creating the NSSavePanel.
One of the comments to the original question pointed me in the right direction though, which was to get rid of the custom WindowController subclass. When I did that, the panel appeared just fine. However, since that's not a great solution (in case you really want to keep your custom class), I kept digging..
FYI, I am using NSStoryboards and building the app for 10.10.
I noticed some weird behavior when I (temporarily) unchecked "Restorable" on my main window--every time the save panel appeared, a new main window of my app appeared. That led me to believe that my app delegate had a major disconnect with the primary window being shown--especially now with storyboards having a separate Application Scene and WindowController.
What I did:
Select my primary window controller and UNCHECK "Is Initial Controller" (i.e. there is no initial controller set for the storyboard)
In my app delegate, in applicationDidFinishLaunching:, I manually created the storyboard and loaded the window controller using instantiateControllerWithIdentifier:
I set the self.window to the created windowController.window property
I made self.window the key and order front (using makeKeyAndOrderFront:)
The app launches, loads the window as before, but now the save panel appears just fine. It also works with a custom windowController subclass.
Finally, as a bonus, I finally have the proper behavior when using applicationShouldTerminateAfterLastWindowClosed (being set to NO)
Short Description:
This look like a bug somehow related to ArrayController and perhaps any other similar controller for that mater or whatever it inherits or the bindings system in IB. Here is a simple code which demonstrates the problem in detail: https://www.dropbox.com/s/atwoc2hweh5fjk6/Bug.zip?dl=0
Long Description:
It looks like that something weird is going on inside the SDK.
In the example that I have provided I have a standard application generated with a standard Xcode 6.1 template. The application is sandboxed. Inside the application delegate we simply test if the NSSavePanel will fire without any problems. The ViewController declares a property called "array" which is later bound to an NSArrayController (see inside Main.storyboard).
If you launch the application in this setup you will see that the NSSavePanel fails. However, if we simply turn off the NSArrayController binding, the call to NSSavePanel miraculously work.
Therefore, it is safe to assume that this is nothing but a bad bug hidden underneath the latest SDK, which apple needs to fix.
Feel free to add the sample to your bug report to Apple.
Woraround:
It looks like if you disable the "Raises For Not Applicable Keys" option inside the array controller binding you get the application to work again without turning off the binding itself. This probably means that an exception is raised before setting up the sandbox connecting to the XPC service therefore making the application misbehave.
The proper fix will be for apple to put the XPC connection initialization code somewhere where it is guarded from weird errors and exceptions therefore ensuring that it is always working.
UPDATE
Based on serenn suggestion I use the following code to make my application behave as expected:
let sb = NSStoryboard(name: "Main", bundle: nil)!
// ---
rootWindowController = sb.instantiateControllerWithIdentifier("MainWindowController") as? NSWindowController
// ---
rootWindowController?.showWindow(self)
In my tests I find that rootWindowController?.showWindow(self) works better to show the window instead of makeKeyAndOrderFront because otherwise the segues don't get properly connected (popups, etc). This method works for me.
According to the App Sandbox Design Guide you should create your own subclass of NSDocument. NSDocument has its own method for presenting the save dialog:
The NSDocument class automatically works with Powerbox. NSDocument also provides support for keeping documents within your sandbox if the user moves them using the Finder.
Remember that the inheritance path of the NSOpenPanel and NSSavePanel classes is different when your app is sandboxed. See Open and Save Dialog Behavior with App Sandbox.
Because of this runtime difference, an NSOpenPanel or NSSavePanel object inherits fewer methods with App Sandbox. If you attempt to send a message to an NSOpenPanel or NSSavePanel object, and that method is defined in the NSPanel, NSWindow, or NSResponder classes, the system raises an exception. The Xcode compiler does not issue a warning or error to alert you to this runtime behavior.

NSOperation crash on isCancelled

I have implemented a concurrent nsoperation and have ARC enabled. Now my customer is experiencing a crash which I cannot reproduce. He sent me the follow crash log :
Date/Time: 2013-04-24 12:23:34.925 -0400
OS Version: Mac OS X 10.8.3 (12D78)
Report Version: 10
Interval Since Last Report: 30946 sec
Crashes Since Last Report: 1
Per-App Interval Since Last Report: 33196 sec
Per-App Crashes Since Last Report: 1
Anonymous UUID: FB8460EE-5199-C6FB-55DC-F927D7F81A80
Crashed Thread: 15 Dispatch queue: com.apple.root.default-priority
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: EXC_I386_GPFLT
Application Specific Information:
objc_msgSend() selector name: isCancelled
Thread 15 Crashed:: Dispatch queue: com.apple.root.default-priority
0 libobjc.A.dylib 0x00007fff877f1250 objc_msgSend + 16
1 Myapp 0x000000010a608807 0x10a601000 + 30727
2 Myapp 0x000000010a650575 0x10a601000 + 324981
3 com.apple.Foundation 0x00007fff8b66212f -[NSBlockOperation main] + 124
4 com.apple.Foundation 0x00007fff8b638036 -[__NSOperationInternal start] + 684
5 com.apple.Foundation 0x00007fff8b63f861 __block_global_6 + 129
6 libdispatch.dylib 0x00007fff832d0f01 _dispatch_call_block_and_release + 15
7 libdispatch.dylib 0x00007fff832cd0b6 _dispatch_client_callout + 8
8 libdispatch.dylib 0x00007fff832ce1fa _dispatch_worker_thread2 + 304
9 libsystem_c.dylib 0x00007fff87d19d0b _pthread_wqthread + 404
10 libsystem_c.dylib 0x00007fff87d041d1 start_wqthread + 13
My code looks like this:
-(void)start
{
// Always check for cancellation before launching the task.
if ([self isCancelled])
{
// Must move the operation to the finished state if it is canceled.
[self onCancelSyncOperation];
return;
}
// If the operation is not canceled, begin executing the task.
[self willChangeValueForKey:#"isExecuting"];
[NSThread detachNewThreadSelector:#selector(main) toTarget:self withObject:nil];
executing = YES;
[self didChangeValueForKey:#"isExecuting"];
}
- (void)onCancelSyncOperation
{
[self willChangeValueForKey:#"isFinished"];
[self willChangeValueForKey:#"isExecuting"];
executing = NO;
finished = YES;
[self didChangeValueForKey:#"isExecuting"];
[self didChangeValueForKey:#"isFinished"];
}
It seems like the nsoperation is already released? when it tries to check for isCancelled?
Is this possible?
I don't think anyone can tell you why your app crashes by looking at this log. I haven't looked at your code, but you cut your crash-log, so it only shows system modules (lib.dispatch..., com.apple...). Typically the error is in the first occurrence of "com.myname...".
If this kind of crash EXC_BAD_ACCESS (SIGSEGV) appears along with an objc_msgSend(), it probably means you're trying to message to an object (or in other words: call a method of an object) that isn't there anymore. If you call that object, chances are very good that you'll find it, if you call it delayed or on another Thread or from a block, it will be a bit more complicated.
Your best chance to find the cause of this is to inspect your app with Instrument, using the Allocations or Leaks tool with NSZombies enabled (which is the default). You can launch Instruments from within Xcode. Then try to reproduce your crash. If you succeed, you might be able to find the class and location where the crash occurs.
If you don't know what to do with this answer, then check out the WWDC Developer Videos from Apple, there are some that show how to profile your app with Instruments (you'll need a [free] Dev Account to access the videos).
Good luck!

NSTimer crashing my application

So I have an application which uses an NSTimer. The problem is that when the NSTimer runs, my application will crash with EXC_BAD_ACCESS. I only just started with objective-c so I don't know how to properly debug it. If I thought call the -(void)logIn{} with [self logIn]; the application will work.
My code:
.h
#interface DJ_WAppDelegate : NSObject {
NSTimer *loginTimer;
}
-(void)logIn;
#end
.m
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
[self logIn]; // this works
loginTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(logIn) userInfo:nil repeats:YES]; // this fails
}
- (void)logIn {
NSLog(#"Logging in...");
// if I comment out these 2 lines it works with the NSTimer!?... (I've would have more code below)
NSURL *loginConn = [NSURL URLWithString:[NSString stringWithFormat:#"some-website.com"]];
NSInteger loginReturn = [[NSString stringWithContentsOfURL:loginConn encoding:NSASCIIStringEncoding error:nil] intValue];
// when "loginReturn" return "OK" the timer (loginTimer) will be stopped with: [loginTimer invalidate];
// more code would be below... (which works!)
}
So the problem is with the NSURL it think.
Thanks for helping.
EDIT 1:
Here's the crash stack:
EException Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x0000000000000020
Crashed Thread: 0 Dispatch queue: com.apple.main-thread
Application Specific Information:
objc_msgSend() selector name: respondsToSelector:
Thread 0 Crashed: Dispatch queue: com.apple.main-thread
0 libobjc.A.dylib 0x9603bed7 objc_msgSend + 23
1 com.apple.CoreFoundation 0x922ed5f2 _CFStringAppendFormatAndArgumentsAux + 3138
2 com.apple.CoreFoundation 0x922ec979 _CFStringCreateWithFormatAndArgumentsAux + 105
3 com.apple.Foundation 0x9656ebfb -[NSPlaceholderString initWithFormat:locale:arguments:] + 163
4 com.apple.Foundation 0x9656eaae +[NSString stringWithFormat:] + 88
5 com.who.DJ-W 0x00001d56 -[DJ_WAppDelegate logIn] + 116 (DJ_WAppDelegate.m:108)
6 com.apple.Foundation 0x965b08d4 __NSFireTimer + 141
7 com.apple.CoreFoundation 0x922ffadb __CFRunLoopRun + 8059
8 com.apple.CoreFoundation 0x922fd464 CFRunLoopRunSpecific + 452
9 com.apple.CoreFoundation 0x922fd291 CFRunLoopRunInMode + 97
10 com.apple.HIToolbox 0x91646e04 RunCurrentEventLoopInMode + 392
11 com.apple.HIToolbox 0x91646bb9 ReceiveNextEventCommon + 354
12 com.apple.HIToolbox 0x91646a3e BlockUntilNextEventMatchingListInMode + 81
13 com.apple.AppKit 0x9265378d _DPSNextEvent + 847
14 com.apple.AppKit 0x92652fce -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 156
15 com.apple.AppKit 0x92615247 -[NSApplication run] + 821
16 com.apple.AppKit 0x9260d2d9 NSApplicationMain + 574
17 com.who.DJ-W 0x00001c92 start + 54
hope this helps... to find the error
EDIT 2:
With the Zombie Mode on I get this: *** -[CFString respondsToSelector:]: message sent to deallocated instance 0x46d550 I hope this helps.
EDIT 3:
To Ball: Here is the original URL (took away the domain here) /DJW/work.php?user=iBlackbirdi&udid=00000000-0000-1000-80005&key=660e5744e&cmd=slocau&type=get
There are several problems here:
djwLog is a class method so you should call it on the class not the instance
like this: [[self class] djwLog:#"foo bar"]
The URLFromString: method needs the string to contain a valid URL as specified by RFC 1808. Something along the lines of [NSURL URLFromString:#"http://example.com/foo"]
stringWithContentsOfURL:url… is a syncornous method. Unless you have this code running in a separate thread you should not use this. Look at NSURLConnection for a class to asynchronously load data from a URL. Using synchronized calls for this is a bad idea. Always.
intValue returns a signed integer. To get a NSInteger use integerValue. Also if you use stringWithContentsOfURL make sure to check if it's result is nil before calling
integerValue otherwise you might get a result of 0 if the URL call failed or did not return data. A real parser for the API you are calling would be a good idea in any case.
You're calling a class method as if it was an instance method:
[self djwLog:#"Logging in..."];
Since there is no instance-method named djwLog the application crashes. You should either call NSLog directly, make it an instance-method - or preferably make a macro for logging:
#ifdef DEBUG
# define DLog(...) NSLog(#"%s %#", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
#else
# define DLog(...) do { } while (0)
#endif
If you instead of NSLog write DLog - it will only be logging when DEBUG-flag has been defined. In addition to this, it will log the origin of the log message - so you can see which class/method the log entry came from.

Array Initialization

The following code for initialization of array works ::
NSArray *array = [[NSArray alloc] initWithObjects:#"Toy Story 3",#"Inception",nil];
self.list = [array sortedArrayUsingSelector:#selector(compare:)];
[array release];
[super viewDidLoad];
But the following code doesnt. The iPhone Simulator Terminates as soon as I try to scroll the Table View which i used to view the array. (Only after i scroll onto empty tableViewCells)
NSBundle *bundle = [NSBundle mainBundle];
NSString *plistPath = [bundle pathForResource:#"MovieList" ofType:#"plist"];
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:plistPath];
NSLog([array objectAtIndex:1]);
self.list = [array sortedArrayUsingSelector:#selector(compare:)];
[array release];
[super viewDidLoad];
This was an example app from the Book "Beginning iPhone Development" by Dave Mark. In the example , they have initialized the array within the code, while i have tried to initialize it from a external file.
The console Log ::
2010-12-22 20:57:43.772 Nav[2474:40b] WARNING: Using legacy cell layout due to delegate implementation of tableView:accessoryTypeForRowWithIndexPath: in <RootViewController: 0x9908870>. Please remove your implementation of this method and set the cell properties accessoryType and/or editingAccessoryType to move to the new cell layout behavior. This method will no longer be called in a future release.
2010-12-22 20:58:12.480 Nav[2474:40b] WARNING: Using legacy cell layout due to delegate implementation of tableView:accessoryTypeForRowWithIndexPath: in <DisclosureButtonController: 0x9b32ab0>. Please remove your implementation of this method and set the cell properties accessoryType and/or editingAccessoryType to move to the new cell layout behavior. This method will no longer be called in a future release.
2010-12-22 20:59:13.299 Nav[2474:40b] -[UIDeviceRGBColor length]: unrecognized selector sent to instance 0x9b3d900
2010-12-22 20:59:13.301 Nav[2474:40b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIDeviceRGBColor length]: unrecognized selector sent to instance 0x9b3d900'
*** Call stack at first throw:
(
0 CoreFoundation 0x00db2be9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x00f075c2 objc_exception_throw + 47
2 CoreFoundation 0x00db46fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x00d24366 ___forwarding___ + 966
4 CoreFoundation 0x00d23f22 _CF_forwarding_prep_0 + 50
5 UIKit 0x0051a9ca -[UITableViewCellLayoutManager layoutSubviewsOfCell:] + 3424
6 UIKit 0x00482e02 -[UITableViewCell layoutSubviews] + 95
7 QuartzCore 0x01c70451 -[CALayer layoutSublayers] + 181
8 QuartzCore 0x01c7017c CALayerLayoutIfNeeded + 220
9 QuartzCore 0x01c6937c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 310
10 QuartzCore 0x01c690d0 _ZN2CA11Transaction6commitEv + 292
11 QuartzCore 0x01c997d5 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 99
12 CoreFoundation 0x00d93fbb __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 27
13 CoreFoundation 0x00d290e7 __CFRunLoopDoObservers + 295
14 CoreFoundation 0x00cf1bd7 __CFRunLoopRun + 1575
15 CoreFoundation 0x00cf1240 CFRunLoopRunSpecific + 208
16 CoreFoundation 0x00cf1161 CFRunLoopRunInMode + 97
17 GraphicsServices 0x016e7268 GSEventRunModal + 217
18 GraphicsServices 0x016e732d GSEventRun + 115
19 UIKit 0x002ca42e UIApplicationMain + 1160
20 Nav 0x00002598 main + 102
21 Nav 0x00002529 start + 53
)
terminate called after throwing an instance of 'NSException'
enter code here
It sounds like this is a perfect job for the debugger, doesn't it? Why not set a breakpoint on the first line and make sure nothing is unexpectedly nil or out of bounds as you step through and inspect your variables? Perhaps paying attention to the error that's undoubtedly logged to the console might be helpful, too?
Given you've mentioned neither the line on which it terminates nor any log messages, this is about as specific as anyone can get.
The first argument to NSLog needs to be an NSString. The object you're passing to it appears to be part of the UIColor cluster. I suggest you change to:
NSLog(#"%#", [array objectAtIndex:1]);
So the first argument is definitely a string and it says just to print a description of whichever object is the next argument.

With proxy, NSURLConnection leaks for https URLs

Instrument reports leak for this simple use of NSURLConnection:
#import <Foundation/Foundation.h>
int main (int argc, char ** argv)
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
NSURLRequest *theRequest = [NSURLRequest
requestWithURL:[NSURL URLWithString:#"https://gmail.com/"]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60.0];
[NSURLConnection connectionWithRequest:theRequest delegate:nil];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5]];
[pool drain];
[NSThread sleepForTimeInterval:10]; // wait for Instruments to check
}
Leak stack trace:
0 CoreFoundation __CFBasicHashRehash
1 CoreFoundation CFDictionaryCreate
2 CFNetwork _getConnectionInfoForProxy
3 CFNetwork HTTPProtocol::createStream()
4 CFNetwork HTTPProtocol::createAndOpenStream()
5 CFNetwork executionContextPerform(void*)
6 CoreFoundation __CFRunLoopDoSources0
7 CoreFoundation __CFRunLoopRun
8 CoreFoundation CFRunLoopRunSpecific
9 CoreFoundation CFRunLoopRunInMode
10 Foundation +[NSURLConnection(NSURLConnectionReallyInternal) _resourceLoadLoop:]
11 Foundation -[NSThread main]
12 Foundation __NSThread__main__
13 libSystem.B.dylib _pthread_start
14 libSystem.B.dylib thread_start
It doesn't leak if the URL is just normal http and it doesn't redirect to a https site.
How do I fix the leak?
I'm using Snow Leopard and I have proxies on for both http and https.
I think you're asking the wrong questions. Here's what you should be asking:
Am I following the memory management rules?
If I am, do I need to worry about this?
In your case, the answers are (respectively) "Yes" and "No". It's quite possible that you have found a memory leak in the Cocoa frameworks. However in this case, I don't think you have. You see, the NSRunLoop for the current thread retains the NSURLConnection, so it's possible that you're just not giving the run loop enough time to release the connection or something.
The point is, you're not doing anything wrong, so Don't Panic.