Skip to content

Enable Android uncaught exception capture - #200

Merged
waltjones merged 5 commits into
masterfrom
wj-android-uncaught-exceptions
Apr 6, 2020
Merged

Enable Android uncaught exception capture#200
waltjones merged 5 commits into
masterfrom
wj-android-uncaught-exceptions

Conversation

@waltjones

@waltjones waltjones commented Mar 27, 2020

Copy link
Copy Markdown
Contributor

Fixes: rollbar/rollbar-react-native#104

This PR fixes several issues preventing uncaught exception capture from working in Android.

Ensures the default sender uses DiskQueue
The previous code looks like it is setting up a DiskQueue, but the conditional if (config.sender() == null) executes after configProvider.provide(defaultConfig) causes build() to be called on the config. At this point, config.sender() can never be null even if the supplied configProvider tries to set it to null. (Keep in mind this doesn't only affect rollbar-react-native, but all Android apps.) So the default ConcurrentLinkedQueue was being used. This won't work for Android uncaught exceptions, because after building the payload the sender will release the thread. The app will terminate, and the payload is lost. With DiskQueue, the payload is stored to disk and sent on the next app start.

This appears to be the pull request where this would have stopped working:
#168

Closes the default sender when a custom sender is present
#168 tried changing the initialization order so this step isn't needed, which led (in part) to the current issue.

Fixes IndexOutOfBoundsException in DiskQueue.poll()
There is a bug where calling poll() (or peek()) tries to reference the first element on the list while the list is empty. The uncaught IndexOutOfBoundsException keeps this queue from working. The exception will be hit anytime the queue of pending payloads is empty when the polling interval triggers.

Uses setDefaultUncaughtExceptionHandler
The existing setUncaughtExceptionHandler is per thread. Even if a public interface were to allow setting this for each thread, for popular frameworks like React Native that create their own threads, this would be impossible for the application to manage. This fix ensures exceptions on all threads will bubble up to the handler. The existing handler-per-thread behavior is preserved for non-android targets.

Updates gradle config to run tests, lint and coverage for the android target.

Adds tests for the android target.

@waltjones waltjones changed the title Enable Android uncaught exception capture WIP: Enable Android uncaught exception capture Mar 27, 2020
@waltjones
waltjones force-pushed the wj-android-uncaught-exceptions branch from cc1d94c to 5da1c01 Compare April 1, 2020 19:44
@waltjones
waltjones changed the base branch from master to wj-test April 1, 2020 19:56
@waltjones
waltjones changed the base branch from wj-test to master April 1, 2020 19:57
@waltjones
waltjones force-pushed the wj-android-uncaught-exceptions branch from 5da1c01 to 3ec6749 Compare April 1, 2020 19:59
@waltjones waltjones changed the title WIP: Enable Android uncaught exception capture Enable Android uncaught exception capture Apr 1, 2020
@waltjones
waltjones requested review from basoko and jondeandres April 1, 2020 20:11
@waltjones waltjones closed this Apr 3, 2020
@waltjones waltjones reopened this Apr 3, 2020

@jondeandres jondeandres left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@basoko can you take a look at this?

DiskQueue queue = new DiskQueue.Builder()
.queueFolder(folder)
.build();
if (config.sender() != sender) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know details about how tihs works, but where config.sender is set and when it can be equal to sender?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sender is the default sender created further up in this method. config.sender is the sender actually applied to the config. It may still be the default, or may have been updated by the configProvider. What this block does is, close the default sender we just created if it was removed from the config.

The != operator will compare the instance of the class, so this will detect if the new sender is a new instance of the same class and still correctly close the default.


private Payload readFromFile(boolean removeFile) {
File eventFile = getFiles().get(0);
List<File> files = getFiles();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

@@ -16,6 +16,12 @@ repositories {

apply plugin: 'com.android.library'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that maybe we should move the rollbar-android to it's own repository at some point, not now, as it's making more complex the build system, In the end they are quite different, its not just a java project. What do you think?

/**
* Handle all uncaught errors on all threads with the current notifier.
*/
public void handleUncaughtErrors() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason to not make the underlying notifier set the UncaughtExceptionHandler as the default one? When the Config.handleUncaughtErrors is set? I think maybe it'd be better to haveit set as the default one instead of only to the current thread.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned about the change in behavior without a major version bump. For Android, it hadn't worked at all, so I'm not worried about it. For other targets, going from per thread to global will be a big change for some setups.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the change in behavior a part of having an uncaught handler for every thread instead of only for the current one in which the notifier is created? I might be wrong, but looks like a fix as now we don't capture all uncaught exceptions...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you say change it, I'll change it. But yes, the existing interface both takes a thread object and specifies in the comment that it's per thread, so I took that to be fully intentional. https://github.com/rollbar/rollbar-java/blob/master/rollbar-java/src/main/java/com/rollbar/notifier/Rollbar.java#L80-L98

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I think we can be conservative with that change and don't do it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Sounds good. I like that this also keeps the current PR in the scope of the Android issue.

If we separate the Android SDK, that might be a good time to plan a major version and update this.

@basoko basoko left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @waltjones !

@waltjones

Copy link
Copy Markdown
Contributor Author

@basoko Thank you!

@waltjones
waltjones merged commit 76ff651 into master Apr 6, 2020
@vselvarajijay
vselvarajijay deleted the wj-android-uncaught-exceptions branch May 22, 2020 14:30
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.

Rollbar Is Not Reporting Crashes Inside Android NativeModules

3 participants