Bug 1043457 - Add Context and unregister options to CrashHandler; r=snorp

This commit is contained in:
Jim Chen 2014-10-20 16:39:20 -04:00
Родитель 7a92608bb3
Коммит 61e38a581e
1 изменённых файлов: 61 добавлений и 8 удалений

Просмотреть файл

@ -16,9 +16,14 @@ class CrashHandler implements Thread.UncaughtExceptionHandler {
private static final String LOGTAG = "GeckoCrashHandler"; private static final String LOGTAG = "GeckoCrashHandler";
private static final Thread MAIN_THREAD = Thread.currentThread(); private static final Thread MAIN_THREAD = Thread.currentThread();
// Context for getting device information
protected final Context appContext;
// Thread that this handler applies to, or null for a global handler
protected final Thread handlerThread;
protected final Thread.UncaughtExceptionHandler systemUncaughtHandler; protected final Thread.UncaughtExceptionHandler systemUncaughtHandler;
protected boolean crashing; protected boolean crashing;
protected boolean unregistered;
/** /**
* Get the root exception from the 'cause' chain of an exception. * Get the root exception from the 'cause' chain of an exception.
@ -58,7 +63,18 @@ class CrashHandler implements Thread.UncaughtExceptionHandler {
* Create and register a CrashHandler for all threads and thread groups. * Create and register a CrashHandler for all threads and thread groups.
*/ */
public CrashHandler() { public CrashHandler() {
systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler(); this((Context) null);
}
/**
* Create and register a CrashHandler for all threads and thread groups.
*
* @param appContext A Context for retrieving application information.
*/
public CrashHandler(final Context appContext) {
this.appContext = appContext;
this.handlerThread = null;
this.systemUncaughtHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this); Thread.setDefaultUncaughtExceptionHandler(this);
} }
@ -68,10 +84,43 @@ class CrashHandler implements Thread.UncaughtExceptionHandler {
* @param thread A thread to register the CrashHandler * @param thread A thread to register the CrashHandler
*/ */
public CrashHandler(final Thread thread) { public CrashHandler(final Thread thread) {
systemUncaughtHandler = thread.getUncaughtExceptionHandler(); this(thread, null);
}
/**
* Create and register a CrashHandler for a particular thread.
*
* @param thread A thread to register the CrashHandler
* @param appContext A Context for retrieving application information.
*/
public CrashHandler(final Thread thread, final Context appContext) {
this.appContext = appContext;
this.handlerThread = thread;
this.systemUncaughtHandler = thread.getUncaughtExceptionHandler();
thread.setUncaughtExceptionHandler(this); thread.setUncaughtExceptionHandler(this);
} }
/**
* Unregister this CrashHandler for exception handling.
*/
public void unregister() {
unregistered = true;
// Restore the previous handler if we are still the topmost handler.
// If not, we are part of a chain of handlers, and we cannot just restore the previous
// handler, because that would replace whatever handler that's above us in the chain.
if (handlerThread != null) {
if (handlerThread.getUncaughtExceptionHandler() == this) {
handlerThread.setUncaughtExceptionHandler(systemUncaughtHandler);
}
} else {
if (Thread.getDefaultUncaughtExceptionHandler() == this) {
Thread.setDefaultUncaughtExceptionHandler(systemUncaughtHandler);
}
}
}
/** /**
* Record an exception stack in logs. * Record an exception stack in logs.
* *
@ -125,13 +174,17 @@ class CrashHandler implements Thread.UncaughtExceptionHandler {
} }
try { try {
this.crashing = true; if (!this.unregistered) {
exc = getRootException(exc); // Only process crash ourselves if we have not been unregistered.
logException(thread, exc);
if (reportException(thread, exc)) { this.crashing = true;
// Reporting succeeded; we can terminate our process now. exc = getRootException(exc);
return; logException(thread, exc);
if (reportException(thread, exc)) {
// Reporting succeeded; we can terminate our process now.
return;
}
} }
if (systemUncaughtHandler != null) { if (systemUncaughtHandler != null) {