Fixed: Do not stop the app if UncaughtExceptionHandler implemented by CrashHandler receives an exception on a non main thread

Rename function that should be used by main thread of apps to `setDefaultCrashHandler()`.

Functions for other threads will be added in a later commit.
This commit is contained in:
agnostic-apollo
2022-04-17 05:54:45 +05:00
parent 5116d886c3
commit 6b60adc079
3 changed files with 27 additions and 17 deletions

View File

@@ -20,7 +20,7 @@ public class TermuxApplication extends Application {
Context context = getApplicationContext(); Context context = getApplicationContext();
// Set crash handler for the app // Set crash handler for the app
TermuxCrashUtils.setCrashHandler(this); TermuxCrashUtils.setDefaultCrashHandler(this);
// Set log config for the app // Set log config for the app
setLogConfig(context); setLogConfig(context);

View File

@@ -19,28 +19,34 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler {
private final Context mContext; private final Context mContext;
private final CrashHandlerClient mCrashHandlerClient; private final CrashHandlerClient mCrashHandlerClient;
private final Thread.UncaughtExceptionHandler defaultUEH; private final Thread.UncaughtExceptionHandler mDefaultUEH;
private final boolean mIsDefaultHandler;
private static final String LOG_TAG = "CrashUtils"; private static final String LOG_TAG = "CrashUtils";
private CrashHandler(@NonNull final Context context, @NonNull final CrashHandlerClient crashHandlerClient) { private CrashHandler(@NonNull final Context context, @NonNull final CrashHandlerClient crashHandlerClient,
this.mContext = context; boolean isDefaultHandler) {
this.mCrashHandlerClient = crashHandlerClient; mContext = context;
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler(); mCrashHandlerClient = crashHandlerClient;
mDefaultUEH = Thread.getDefaultUncaughtExceptionHandler();
mIsDefaultHandler = isDefaultHandler;
} }
public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) { public void uncaughtException(@NonNull Thread thread, @NonNull Throwable throwable) {
Logger.logInfo(LOG_TAG, "uncaughtException() for " + thread + ": " + throwable.getMessage()); Logger.logInfo(LOG_TAG, "uncaughtException() for " + thread + ": " + throwable.getMessage());
logCrash(thread, throwable); logCrash(thread, throwable);
defaultUEH.uncaughtException(thread, throwable);
// Don't stop the app if not on the main thread
if (mIsDefaultHandler)
mDefaultUEH.uncaughtException(thread, throwable);
} }
/** /**
* Set default uncaught crash handler of current thread to {@link CrashHandler}. * Set default uncaught crash handler for the app to {@link CrashHandler}.
*/ */
public static void setCrashHandler(@NonNull final Context context, @NonNull final CrashHandlerClient crashHandlerClient) { public static void setDefaultCrashHandler(@NonNull final Context context, @NonNull final CrashHandlerClient crashHandlerClient) {
if (!(Thread.getDefaultUncaughtExceptionHandler() instanceof CrashHandler)) { if (!(Thread.getDefaultUncaughtExceptionHandler() instanceof CrashHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(context, crashHandlerClient)); Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(context, crashHandlerClient, true));
} }
} }
@@ -56,7 +62,7 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler {
@NonNull CrashHandlerClient crashHandlerClient, @NonNull CrashHandlerClient crashHandlerClient,
@NonNull Thread thread, @NonNull Throwable throwable) { @NonNull Thread thread, @NonNull Throwable throwable) {
Logger.logInfo(LOG_TAG, "logCrash() for " + thread + ": " + throwable.getMessage()); Logger.logInfo(LOG_TAG, "logCrash() for " + thread + ": " + throwable.getMessage());
new CrashHandler(context, crashHandlerClient).logCrash(thread, throwable); new CrashHandler(context, crashHandlerClient, false).logCrash(thread, throwable);
} }
public void logCrash(@NonNull Thread thread, @NonNull Throwable throwable) { public void logCrash(@NonNull Thread thread, @NonNull Throwable throwable) {
@@ -99,7 +105,7 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler {
/** /**
* Called before {@link #logCrashToFile(Context, CrashHandlerClient, Thread, Throwable)} is called. * Called before {@link #logCrashToFile(Context, CrashHandlerClient, Thread, Throwable)} is called.
* *
* @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient)}. * @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient, boolean)}.
* @param thread The {@link Thread} in which the crash happened. * @param thread The {@link Thread} in which the crash happened.
* @param throwable The {@link Throwable} thrown for the crash. * @param throwable The {@link Throwable} thrown for the crash.
* @return Should return {@code true} if crash has been handled and should not be logged, * @return Should return {@code true} if crash has been handled and should not be logged,
@@ -110,7 +116,7 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler {
/** /**
* Called after {@link #logCrashToFile(Context, CrashHandlerClient, Thread, Throwable)} is called. * Called after {@link #logCrashToFile(Context, CrashHandlerClient, Thread, Throwable)} is called.
* *
* @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient)}. * @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient, boolean)}.
* @param thread The {@link Thread} in which the crash happened. * @param thread The {@link Thread} in which the crash happened.
* @param throwable The {@link Throwable} thrown for the crash. * @param throwable The {@link Throwable} thrown for the crash.
*/ */
@@ -119,7 +125,7 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler {
/** /**
* Get crash log file path. * Get crash log file path.
* *
* @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient)}. * @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient, boolean)}.
* @return Should return the crash log file path. * @return Should return the crash log file path.
*/ */
@NonNull @NonNull
@@ -128,7 +134,7 @@ public class CrashHandler implements Thread.UncaughtExceptionHandler {
/** /**
* Get app info markdown string to add to crash log. * Get app info markdown string to add to crash log.
* *
* @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient)}. * @param context The {@link Context} passed to {@link CrashHandler#CrashHandler(Context, CrashHandlerClient, boolean)}.
* @return Should return app info markdown string. * @return Should return app info markdown string.
*/ */
String getAppInfoMarkdownString(Context context); String getAppInfoMarkdownString(Context context);

View File

@@ -48,8 +48,12 @@ public class TermuxCrashUtils implements CrashHandler.CrashHandlerClient {
} }
/** /**
* Set default uncaught crash handler of current thread to {@link CrashHandler} for Termux app * Set default uncaught crash handler of the app to {@link CrashHandler} for Termux app
* and its plugin to log crashes at {@link TermuxConstants#TERMUX_CRASH_LOG_FILE_PATH}. * and its plugins to log crashes at {@link TermuxConstants#TERMUX_CRASH_LOG_FILE_PATH}.
*/
public static void setDefaultCrashHandler(@NonNull final Context context) {
CrashHandler.setDefaultCrashHandler(context, new TermuxCrashUtils(TYPE.UNCAUGHT_EXCEPTION));
}
*/ */
public static void setCrashHandler(@NonNull final Context context) { public static void setCrashHandler(@NonNull final Context context) {
CrashHandler.setCrashHandler(context, new TermuxCrashUtils(TYPE.UNCAUGHT_EXCEPTION)); CrashHandler.setCrashHandler(context, new TermuxCrashUtils(TYPE.UNCAUGHT_EXCEPTION));