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

Feature/crash loop detection #80

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions backtrace-library/src/main/cpp/backends/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,29 @@ void Disable() {
"Disable not supported on this backend");
#endif
}

jboolean EnableCrashLoopDetectionBackend() {
#ifdef CRASHPAD_BACKEND
return EnableCrashLoopDetectionCrashpad();
#elif BREAKPAD_BACKEND
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "EnableCrashLoopDetection not supported on this backend");
#endif
}

jboolean IsSafeModeRequiredBackend() {
#ifdef CRASHPAD_BACKEND
return IsSafeModeRequiredCrashpad();
#elif BREAKPAD_BACKEND
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "IsSafeModeRequired not supported on this backend");
#endif
}

jint ConsecutiveCrashesCountBackend() {
#ifdef CRASHPAD_BACKEND
return ConsecutiveCrashesCountCrashpad();
#elif BREAKPAD_BACKEND
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "ConsecutiveCrashesCount not supported on this backend");
#endif
}

}
43 changes: 39 additions & 4 deletions backtrace-library/src/main/cpp/backends/crashpad-backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <jni.h>
#include <libgen.h>

//#include "client/crashpad_client.h"

extern std::string thread_id;
extern std::atomic_bool initialized;
extern std::mutex attribute_synchronization;
Expand All @@ -11,6 +13,8 @@ extern std::atomic_bool disabled;
static crashpad::CrashpadClient *client;
static std::unique_ptr<crashpad::CrashReportDatabase> database;

static int consecutive_crashes_count = 0;

bool InitializeCrashpad(jstring url,
jstring database_path,
jstring handler_path,
Expand All @@ -19,6 +23,9 @@ bool InitializeCrashpad(jstring url,
jobjectArray attachmentPaths,
jboolean enableClientSideUnwinding,
jint unwindingMode) {

__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "Initialize Crashpad Start");

// avoid multi initialization
if (initialized) {
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "Crashpad is already initialized");
Expand Down Expand Up @@ -120,9 +127,19 @@ bool InitializeCrashpad(jstring url,

// Start crash handler
client = new crashpad::CrashpadClient();

initialized = client->StartHandlerAtCrash(handler, db, db, backtraceUrl, attributes,
arguments);
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "Crashpad created.");
client->EnableCrashLoopDetection();
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm wondering if we want to make this configurable for the end-users.

Copy link
Collaborator

Choose a reason for hiding this comment

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

i think we should - imo we should pass it and don't execute this path if we don't need it. By default we want have features opt-in

Choose a reason for hiding this comment

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

removed it - it is called from Example's MainActivity now.


// Get consecutive crashes count BEFORE any handler started,
// as it writes extra line into CSV, what leads to getting 0 for each next ConsecutiveCrashesCount call
consecutive_crashes_count = crashpad::CrashpadClient::ConsecutiveCrashesCount(db);
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "Crashpad initialize - ConsecutiveCrashesCount %d", consecutive_crashes_count);
// initialized = client->StartHandler(handler, db, db, backtraceUrl, attributes, arguments, false, false);
// handler, db, db, url, annotations, arguments, false, false, {}
// Original
initialized = client->StartHandlerAtCrash(handler, db, db, backtraceUrl, attributes, arguments);
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "Crashpad initialized %s", (initialized ? "TRUE" : "FALSE"));
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "Crashpad db: %s", filePath);

env->ReleaseStringUTFChars(url, backtraceUrl);
env->ReleaseStringUTFChars(handler_path, handlerPath);
Expand Down Expand Up @@ -219,10 +236,28 @@ void ReEnableCrashpad() {
// Re-enable uploads if disabled
if (disabled) {
if (database == nullptr) {
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "Crashpad database is null, this should not happen");
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android",
"Crashpad database is null, this should not happen");
return;
}
database->GetSettings()->SetUploadsEnabled(true);
disabled = false;
}
}

bool EnableCrashLoopDetectionCrashpad() {
__android_log_print(ANDROID_LOG_ERROR, "Backtrace-Android", "Inside EnableCrashLoopDetectionCrashpad");
if (client != nullptr) {
return client->EnableCrashLoopDetection();
} else {
return false;
}
}

bool IsSafeModeRequiredCrashpad() {
return consecutive_crashes_count >= 5;
}

int ConsecutiveCrashesCountCrashpad() {
return consecutive_crashes_count;
}
18 changes: 18 additions & 0 deletions backtrace-library/src/main/cpp/backtrace-native.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,22 @@ Java_backtraceio_library_BacktraceDatabase_disable(JNIEnv *env, jobject thiz) {
Disable();
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_backtraceio_library_base_BacktraceBase_EnableCrashLoopDetectionBacktrace(JNIEnv *env, jclass clazz) {
return EnableCrashLoopDetectionBackend();
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_backtraceio_library_base_BacktraceBase_IsSafeModeRequiredBacktrace(JNIEnv *env, jclass clazz) {
return IsSafeModeRequiredBackend();
}

extern "C"
JNIEXPORT jint JNICALL
Java_backtraceio_library_base_BacktraceBase_ConsecutiveCrashesCountBacktrace(JNIEnv *env, jclass clazz) {
return ConsecutiveCrashesCountBackend();
}

}
2 changes: 1 addition & 1 deletion backtrace-library/src/main/cpp/crashpad
Submodule crashpad updated 1124 files
6 changes: 6 additions & 0 deletions backtrace-library/src/main/cpp/include/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ void DumpWithoutCrash(jstring message, jboolean set_main_thread_as_faulting_thre
void AddAttribute(jstring key, jstring value);

void Disable();

jboolean EnableCrashLoopDetectionBackend();

jboolean IsSafeModeRequiredBackend();

jint ConsecutiveCrashesCountBackend();
}

#endif //BACKTRACE_ANDROID_BACKEND_H
4 changes: 4 additions & 0 deletions backtrace-library/src/main/cpp/include/crashpad-backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ void DisableCrashpad();

void ReEnableCrashpad();

bool EnableCrashLoopDetectionCrashpad();
bool IsSafeModeRequiredCrashpad();
int ConsecutiveCrashesCountCrashpad();

#endif //BACKTRACE_ANDROID_CRASHPAD_BACKEND_H
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,10 @@ public void nativeCrash() {

public native void dumpWithoutCrash(String message, boolean setMainThreadAsFaultingThread);

public static native boolean EnableCrashLoopDetectionBacktrace();
public static native boolean IsSafeModeRequiredBacktrace();
public static native int ConsecutiveCrashesCountBacktrace();

/**
* Sending an exception to Backtrace API
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,30 @@ protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);

// Set this value in your local.properties
if (BuildConfig.BACKTRACE_SUBMISSION_URL != null) {
backtraceClient = initializeBacktrace(BuildConfig.BACKTRACE_SUBMISSION_URL);
}
String BACKTRACE_SUBMISSION_URL = "https://submit.backtrace.io/konst-ryab/04aecb6b3da05e8d83f2a27f9b5f41352ac792428c5e5f6a94ff58d43ee14e46/json";
// if (BACKTRACE_SUBMISSION_URL != null) {
backtraceClient = initializeBacktrace(BACKTRACE_SUBMISSION_URL);

Context context = getApplicationContext();
String dbPath = context.getFilesDir().getAbsolutePath() + "/crashpad";

String csvPath = dbPath + "/crash_loop_detection.csv";
File file = new File(csvPath);
Log.d("Backtrace-Android", "CSV file exists: " + (file.exists() ? "TRUE" : "FALSE"));
Log.d("Backtrace-Android", "DB path: " + dbPath);
Log.d("Backtrace-Android", "CSV path: " + csvPath);

boolean isCLSafeModeReq = BacktraceClient.IsSafeModeRequiredBacktrace();
int crashesCountCL = BacktraceClient.ConsecutiveCrashesCountBacktrace();
Log.d("Backtrace-Android", "IsSafeModeRequiredCrashpad: " + isCLSafeModeReq);
Log.d("Backtrace-Android", "ConsecutiveCrashesCountCrashpad: " + crashesCountCL);

View viewBackground = findViewById(R.id.viewBackground);
if(viewBackground != null) {
viewBackground.setBackgroundColor(isCLSafeModeReq
? getResources().getColor(R.color.colorAccent)
: getResources().getColor(R.color.colorWhite));
}
symlinkAndWriteFile();
}

Expand Down
8 changes: 7 additions & 1 deletion example-app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<View
android:id="@+id/viewBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorWhite"/>
<Button
android:id="@+id/handledException"
android:layout_width="wrap_content"
Expand Down
1 change: 1 addition & 0 deletions example-app/src/main/res/values/colors.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
<color name="colorPrimary">#008577</color>
<color name="colorPrimaryDark">#00574B</color>
<color name="colorAccent">#D81B60</color>
<color name="colorWhite">#FFFFFF</color>
</resources>