Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Record NSException details immediately from C++ handler #313

Merged
merged 2 commits into from
Sep 13, 2018

Conversation

kattrali
Copy link
Contributor

@kattrali kattrali commented Sep 13, 2018

Goal

Record exception details separately from the NSException call chain.

This avoids a case where if the NSException handler is overridden
without calling the previous handler, no report is recorded. In the case
that the handler is invoked twice for a given exception, it is only
recorded once by checking that the last recorded exception is the same.

Design

When an NSException is thrown, it is first captured in the C++ termination handler.
Once it is then detected to be an NSException, it is ignored in favor of letting the default NSException handler chain catch it (which is invoked by the default C++ handler). This presents a case where an exception is detected but then lost if the NSException handler is overridden.

If we simply call the exception handler logic early, the app may enter an indeterminate state depending on what other handlers do, and there is the possibility that handlers are called once, twice, or not at all.

Good citizenship here would be to:

  1. Capture as many errors as possible
  2. Preserve the end user's ability to override handlers (C++, NSException, signals)
  3. Play nice and call other handlers if previously set
  4. Avoid in all circumstances the chance of calling a handler more than once.

With those goals in mind, this change records details about an NSException immediately from the C++ handler, without invoking/interrupting the uncaught NSException handler chain.

If the same exception is then re-encountered by the uncaught NSException handler, the report is not recorded again and instead invokes the previous handler, if any.

Changeset

Added

  • Added bsg_recordException to the NSException handler. This allows the logic for recording a report to be reused outside of the uncaught exception handler itself.
  • Added bsg_lastHandledException. This variable tracks what exception was last recorded.

Changed

  • Changed the C++ handler to call bsg_recordException immediately when an NSException is detected.

Tests

This change was tested on iOS 8.4/10.3/11.4 and macOS 10.12 and confirmed to send a single report when an NSException is thrown in the following scenarios:

  • Bugsnag is installed and no other handlers are present
  • A custom C++ handler and/or NSException handler is installed before Bugsnag
  • A custom C++ handler and/or NSException handler is installed after Bugsnag, whether or not they call previous handlers. (Depends on mach PR)

Discussion

Linked issues

Closes #312

Review

For the submitter, initial self-review:

  • Commented on code changes inline explain the reasoning behind the approach
  • Reviewed the test cases added for completeness and possible points for discussion
  • A changelog entry was added for the goal of this pull request
  • Check the scope of the changeset - is everything in the diff required for the pull request?

This pull request is ready for final review

For the pull request reviewer(s), this changeset has been reviewed for:

  • Consistency across platforms for structures or concepts added or modified
  • Consistency between the changeset and the goal stated above
  • Internal consistency with the rest of the library - is there any overlap between existing interfaces and any which have been added?
  • Usage friction - is the proposed change in usage cumbersome or complicated?
  • Performance and complexity - are there any cases of unexpected O(n^3) when iterating, recursing, flat mapping, etc?
  • Concurrency concerns - if components are accessed asynchronously, what issues will arise
  • Thoroughness of added tests and any missing edge cases
  • Idiomatic use of the language

@kattrali kattrali force-pushed the kattrali/record-nsexception-immediately branch from 76f467c to 0c1c406 Compare September 13, 2018 01:35
This avoids a case where if the NSException handler is overridden
without calling the previous handler, no report is recorded. In the case
that the handler is invoked twice for a given exception, it is only
recorded once by checking that the last recorded exception is the same.
@kattrali kattrali force-pushed the kattrali/record-nsexception-immediately branch from 0c1c406 to 93a08d7 Compare September 13, 2018 01:48
@kattrali kattrali merged commit eb3594d into master Sep 13, 2018
@kattrali kattrali deleted the kattrali/record-nsexception-immediately branch September 13, 2018 23:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant