NSInvalidArgumentException can't be caught

Originator:dmaclach
Number:rdar://8081169 Date Originated:6/10/2010
Status:OPEN Resolved:
Product:iPhoneSDKq Product Version:3.2 and 4.0
Classification:Serious Bug Reproducible:Always
 
Summary:
You can no longer catch NSInvalidArgumentExceptions that are thrown when you call a method on an object that doesn't have that method.

Steps to Reproduce:
1) Build and run attached code

Interesting stuff is in ExceptionTestAppDelegate application:didFinishLaunchingWithOptions:.

Expected Results:
Should see "Caught" logged to console.

Actual Results:

2010-06-10 14:28:34.643 ExceptionTest[7524:207] -[ExceptionTestAppDelegate bogusMethod]: unrecognized selector sent to instance 0x5c42430
2010-06-10 14:28:34.646 ExceptionTest[7524:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[ExceptionTestAppDelegate bogusMethod]: unrecognized selector sent to instance 0x5c42430'
*** Call stack at first throw:
(
	0   CoreFoundation                      0x0238b919 __exceptionPreprocess + 185
	1   libobjc.A.dylib                     0x024d95de objc_exception_throw + 47
	2   CoreFoundation                      0x0238d42b -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
	3   CoreFoundation                      0x022fd116 ___forwarding___ + 966
	4   CoreFoundation                      0x022fccd2 _CF_forwarding_prep_0 + 50
	5   ExceptionTest                       0x000026c4 -[ExceptionTestAppDelegate application:didFinishLaunchingWithOptions:] + 77
	6   UIKit                               0x002b0543 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
	7   UIKit                               0x002b29a1 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 346
	8   UIKit                               0x002bc452 -[UIApplication handleEvent:withNewEvent:] + 1958
	9   UIKit                               0x002b5074 -[UIApplication sendEvent:] + 71
	10  UIKit                               0x002b9ac4 _UIApplicationHandleEvent + 7495
	11  GraphicsServices                    0x02bf1afa PurpleEventCallback + 1578
	12  CoreFoundation                      0x0236cdc4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
	13  CoreFoundation                      0x022cd737 __CFRunLoopDoSource1 + 215
	14  CoreFoundation                      0x022ca9c3 __CFRunLoopRun + 979
	15  CoreFoundation                      0x022ca280 CFRunLoopRunSpecific + 208
	16  CoreFoundation                      0x022ca1a1 CFRunLoopRunInMode + 97
	17  UIKit                               0x002b2226 -[UIApplication _run] + 625
	18  UIKit                               0x002bdb58 UIApplicationMain + 1160
	19  ExceptionTest                       0x00002654 main + 102
	20  ExceptionTest                       0x000025e5 start + 53
	21  ???                                 0x00000001 0x0 + 1
)
terminate called after throwing an instance of 'NSException'

Regression:
This works on SDKs before 3.2. Also is broken on 4.0

Notes:
This breaks tests in Google Toolbox for Mac.

Comments

iPad simulator as well

Just to pile-on. I cannot seem to catch exceptions in the iPad (3.2) simulator either.

Confirmed on iOS 4.0 simulator only

I'm working on a new mock object library that has the ability to tell a mocked/stubbed method to raise an exception. Naturally, it does this by capturing the invocation and injecting it that way so I've run into this bug too. My acceptance test case (just a SenTest method) passes with the device SDK but fails with the simulator SDK.

I've filed a dupe: http://openradar.appspot.com/radar?id=548401

Affects also 4.0.1 and 4.1 beta

Simulators shipped with iOs SDK 4.0.1 and 4.1 beta still suffer from this bug.

Also applies to methods dispatched through forwarding....

code like

@try {
    [self methodThatDoesNotExist];  
}
@catch (NSException *e) {
    NSLog(@"caught!");
}

will not catch anything....

I filed a bug report with Apple about this too.

Simulator only

With further testing, this appears to affect the simulator only. Works on the device.

Yes so it seems! Tested and confirmed for iOS 3.1.3 and 4.0.

By nicky.vault13 at July 6, 2010, 7:33 a.m. (reply...)

Can't throw exceptions across NSInvocations

Apparently the problem is even worse where exceptions can't be thrown across [NSInvocation invoke] calls.

I can catch exceptions if I do this:

@try { NSInvocation invocation = [self invocation]; objc_msgSend(self, [invocation selector]); } @catch (NSException e) { NSLog(@"%@", e); } but not this

@try { NSInvocation invocation = [self invocation]; [invocation invokeWithTarget:self]; } @catch (NSException e) { NSLog(@"%@", e); }

It doesn't matter what type of exception it is.

Sigh.

Confirmed

I can confirm this for iOS 4.0.

By nicky.vault13 at June 30, 2010, 2:21 p.m. (reply...)

Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!