6 Replies
      Latest reply on May 9, 2019 1:09 AM by eskimo
      sweatervest Level 1 Level 1 (0 points)

        I use Crashlytics to generate crash reports for an iOS app.  When C++ exceptions are thrown on the main thread, they are caught by a CFRunLoop exception handler and rethrown, which destroys all the information about where in the code the original exception is thrown.

         

        There is an open radar for this, opened two years ago, that was marked as "duplicate", but the duplicate doesn't exist as far as I can tell: http://www.openradar.me/radar?id=4943586562932736

         

        This is a Stackoverflow thread about the issue: https://stackoverflow.com/questions/13777446/ios-how-to-get-stack-trace-of-an-unhandled-stdexception

         

        I've tried all sorts of workarounds, including printing the stack trace with [NSThread callStackSymbols] in the constructor for the exception I use.  This sort of works in debug builds (at least I can see the trace, but Crashlytics still lumps them all into "std::terminate").  But this does not work in release builds.  The symbols are random symbols that don't correspond at all to the actual stack trace.  The end result is that I have no usable stack information for any crashes on the main thread from C++ exceptions, which is unfortunate because my whole app is written in C++.

         

        It's been several years since this was reported to Apple.  The proper solution is to allow us to turn off the CFRunLoop exception trapper.  Should I file another radar (hopefully it won't also be closed as duplicate) or what else should I do to draw Apple's attention to this?  Being unable to report C++ exceptions is a pretty big deal.

        • Re: C++ exceptions on iOS
          john daniel Level 3 Level 3 (400 points)

          Apple platforms in general don't support exceptions, even if the underlying languages do. If your code uses exceptions, or calls any Apple code that could throw exceptions, then you need to wrap your code in exception handlers. Considering how much effort that is likely to be, it is easier to just not throw exceptions. That will leave you with a much smaller set of places where you still have to catch Apple-thrown exceptions. They aren't common, but they do exist, and not always where you might expect.

          • Re: C++ exceptions on iOS
            eskimo Apple Staff Apple Staff (11,825 points)

            Should I file another radar … ?

            Yes.  The bug you mentioned (r. 29407867) was closed as a dup of another bug (r. 28409982) that has since been closed.  That second bug was closed as fixed, but the fix isn’t what you were looking for [1].  The new behaviour is correct from the run loop’s perspective, but if it’s causing problem with your third-party crash reporter then it’s reasonable for you to file a new bug about that.

            Having said that, I strongly discourage folks from using third-party crash reporters.  I have a lot to say on this subject in my Implementing Your Own Crash Reporter post.

            Share and Enjoy

            Quinn “The Eskimo!”
            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
            let myEmail = "eskimo" + "1" + "@apple.com"

            [1] Specifically:

            • The previous behaviour is that it would catch the language exception and attempt to keep running the run loop.  That is never a good idea.

            • The new behaviour is that it catches the language exception and terminates the process, which is a marked improvement.

            • I’m not exactly sure what you want it to do, because it depends on how your third-party crash reporter is expecting to be presented with language exceptions.  I recommend that you research that so that you can file a focused bug.

              • Re: C++ exceptions on iOS
                sweatervest Level 1 Level 1 (0 points)

                Thank you for your response.

                 

                The use of a 3rd party reporter (which provides a lot more features regarding analytics that are crucial to analysis of crashes) isn't the issue.  The Apple crash report for a C++ exception shows the same thing Crashlyics shows, which is always this:

                 

                8  libc++abi.dylib                0x1a27a0838 std::__terminate(void (*)()) + 16

                9  libc++abi.dylib                0x1a27a0434 __cxa_rethrow + 144

                10 libobjc.A.dylib                0x1a27abbc8 objc_exception_rethrow + 44

                11 CoreFoundation                 0x1a355c3c0 CFRunLoopRunSpecific + 544

                12 GraphicsServices               0x1a575c79c GSEventRunModal + 104

                13 UIKitCore                      0x1cf9cfb68 UIApplicationMain + 212

                14 --------------                  0x1009ded50 main (main.m:16)

                15 libdyld.dylib                  0x1a30228e0 start + 4

                 

                Because it catches and rethrows the exception.  All information about where it came from is lost.

                 

                What I want the run loop to do is (optionally) simply not catch C++ exceptions.  If all it does when catching an exception is call terminate, which is what happens when an uncaught exception is thrown, what's the point?  The only effect as far as I can tell of catching and rethrowing it is that terminate always gets called from the run loop stack instead of the stack where the exception originated, which makes debugging much more difficult.

                 

                @john, wrapping the code in an try-catch won't fix this problem, in fact that *is* the problem.  The CFRunLoop wraps everything on the main thread in a try-catch loop, which is why the stack frame is lost.  Refactoring the code to not use C++ exceptions is not really an acceptable option either.  Exceptions are, for many reasons, the preferred way to handle exceptional situations/errors in modern C++ code (differences of opinion notwithstanding, I've read both sides and made the decision judiciously), and while it would be unfortunate to be unable to analyze crashes originating from Apple platforms, I'd be more willing to do that than introduce design workarounds for a code base designed to support many platforms.

                 

                I already filed a bug report with Apple, hopefully they will respond.  As I said, I would think that if this impacts all C++ exception-throwing code in iOS apps it's severe enough to warrant attention.

                  • Re: C++ exceptions on iOS
                    eskimo Apple Staff Apple Staff (11,825 points)

                    The Apple crash report for a C++ exception shows the same thing Crashlyics shows …

                    I was surprised by that assertion (I see a lot of crash reports with exception information in them), so I decided to run some tests.  It turns out that, when the exception gets caught by the run loop, the last exception information only makes it into the crash report for Objective-C exceptions, not for C++ ones.  That surprised me because Objective-C and C++ use the same exception mechanism on modern systems.  It seems that the code to record the backtrace and render it to the Last Exception Backtrace section of the crash report is Objective-C specific.

                    What I want the run loop to do is (optionally) simply not catch C++ exceptions.

                    And, realistically, if someone were implementing the run loop today, that’s how it’d work.  The reasons why the run loop works the way it currently works are mired in the depths of history.

                    I already filed a bug report with Apple, hopefully they will respond.

                    What was the bug number?  I want to make sure it’s clear about two points:

                    • That this affects Apple crash reports, and thus any mention of third-party crash reports is a red herring

                    • That this is specific to C++ exceptions

                    Share and Enjoy

                    Quinn “The Eskimo!”
                    Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                    let myEmail = "eskimo" + "1" + "@apple.com"

                      • Re: C++ exceptions on iOS
                        sweatervest Level 1 Level 1 (0 points)

                        Bug report is here: https://bugreport.apple.com/web/?problemID=50481364

                        There is no mention of third party reporters in the bug description, although the sample stack trace I uploaded shows some Crashlytics functions in the stack.  I just uploaded another one that is identical to what I posted in the reply above.

                         

                        Thank you for looking into this!  Let me know if you need any more info.

                          • Re: C++ exceptions on iOS
                            eskimo Apple Staff Apple Staff (11,825 points)

                            Bug report is here

                            Thanks!  I looked at your bug (r. 50481364) and it’s definitely landed in the right place and been interpreted correctly.  Alas, I can’t offer any predictions as to when it might be resolved.

                            Share and Enjoy

                            Quinn “The Eskimo!”
                            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                            let myEmail = "eskimo" + "1" + "@apple.com"