Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Tools
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker

Objective-C exceptions thrown inside methods invoked via NSInvocation are uncatchable

Adam Milligan
Thursday, July 1, 2010

Whether you’re using Cedar or not, if you’ve upgraded to the iOS 4.0 SDK you may have run into some odd behavior with exception handling blocks not catching exceptions. Strangely, the problem isn’t due to the exceptions themselves (at least not in any obvious way), but with how you call functions that raise exceptions. An exception thrown from within a method you invoke directly will function as expected. However, if you invoke that same function indirectly using NSInvocation any exception thrown becomes uncatchable, crashing the current process regardless of any exception handling code.

This happens only when running against the currently available iOS 4.0 SDK. Exception handling for both direct and indirect invocations performs as expected when using the OS X 10.6 SDK and previous versions of the iPhone SDK.

You can reproduce this problem yourself easily enough. Just create any old iPhone project, and add the following code in a method you know will run (e.g. viewDidLoad on the main controller):

@try {
    NSException *exception = [NSException exceptionWithName:@"foo" reason:@"bar" userInfo:nil];
    [exception raise];
} @catch (NSException *x) {
    NSLog(@"========================> %@", x);
}

Works, right? Now try this (which should be functionally identical):

@try {
    NSException *exception = [NSException exceptionWithName:@"foo" reason:@"bar" userInfo:nil];

    SEL selector = @selector(raise);
    NSMethodSignature *signature = [exception methodSignatureForSelector:selector];
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];

    [invocation setTarget:exception];
    [invocation setSelector:selector];
    [invocation invoke];
} @catch (NSException *x) {
    NSLog(@"========================> %@", x);
}

BOOM! Stack trace. Sad face.

Unfortunately, the OCHamcrest matcher library uses indirect method invocations to raise matcher failure exceptions. So, with iOS 4.0 rather than getting failure messages in your test output, you now get a stack trace and potentially a bunch of un-run tests.

Hopefully Apple will fix this soon.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

9 Comments

  1. Justin DeWind says:

    Yeah, it is an unfortunate bug in the iOS 4 Simulator platform. The bug does not manifest itself on the device. I originally reported the issue to the google toolbox guys (who had seen it before). It has since been posted to http://lists.apple.com/archives/objc-language//2010/Jul/msg00007.html and confirmed as a bug by Greg Parker of Apple.

    July 5, 2010 at 1:50 pm

  2. Justin DeWind says:

    It also manifests itself in NSProxy if you raise an exception within a forward invocation.

    July 5, 2010 at 1:55 pm

  3. Marco Sandrini says:

    Unluckily the problem is still present in simulators shipping with iOs SDKs 4.0.1 and 4.1 beta…

    Very very very frustrating…

    July 20, 2010 at 5:28 am

  4. Adam Milligan says:

    Indeed! I was hoping a fix for this problem would be somewhere in that 5GB download, but Apple doesn’t seem to think it’s important enough to fix quickly.

    July 20, 2010 at 5:51 am

  5. Marco Sandrini says:

    For us, this bug is a blocker, preventing upgrading to the latest version of the SDK (most likely we will move to some sort of dual installation of XCode using < 3.2 to run unit tests and > 3.2 to build the device version) . Oddly enough, to the present day the number of people who have raised this issue are below 5 (of which 3 have commented this post). Makes me wonder what is the common practice when developing sw for the iPhone…

    July 20, 2010 at 8:51 am

  6. Adam Milligan says:

    Marco, how is the bug blocking you? I found it renders OCHamcrest (for example) unusable out of the box, but I was able to patch the way it reports errors to work around the problem (see [this commit](http://github.com/pivotal/OCHamcrest/commit/b05831743c314883a3a077669b009a91a49b7cf8) on github). I used a little dynamic type hackery to change the implicit method to an explicit method; I’m told you can also use objc_msgSend() to fix the problem.

    July 20, 2010 at 9:07 am

  7. Marco Sandrini says:

    We had two sources of problem, OCHamcrest (for which I thank you already for the patch) and some extra features we built on top of OCMock, for which I have been too lazy to go and replace NSInvocation(s) which calls to objc_msgSend as I was still hoping that I would not need to do any workaround (read: I was hoping Apple would fix this).

    Once more thanks for your help!!!

    July 20, 2010 at 9:16 am

  8. Luke Redpath says:

    I’ve also run into this problem whilst working on my Objective-C mock library, Mocky [1]. I’ve filed a dupe: rdar://8237699, see http://openradar.appspot.com/radar?id=548401

    July 26, 2010 at 6:19 pm

  9. Luke Redpath says:

    Missed the footnote:
    [1] http://github.com/lukeredpath/LRMocky

    The specific commit where I hit this bug:
    http://github.com/lukeredpath/LRMocky/commit/c18bd3e3c38608e58e9d23523795e17bd31112e5

    July 26, 2010 at 6:27 pm

Add New Comment Cancel reply

Your email address will not be published.

Adam Milligan

Adam Milligan
New York

Recent Posts

  • Why not to use ARC
  • Cedar Expectations
  • The Trouble With Expectations in Objective C
Subscribe to Adam's Feed

Author Topics

blocks (2)
cplusplus (4)
ios (10)
objective-c (13)
cedar (11)
testing (16)
opensource (5)
xcode4 (1)
rake (4)
access control (3)
ci (2)
jasmine (1)
javascript (3)
ie6 (1)
addiction (1)
activerecord (7)
nested_attributes (1)
rails (12)
actionpack (1)
refactoring (1)
agile (4)
ruby (8)
actionview (1)
threads (1)
functors (2)
brownbags (2)
solr (1)
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Tools
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >