Bug 1066760 - Redirect mozalloc_abort through Java exception handling; r=snorp

This commit is contained in:
Jim Chen 2014-09-24 14:12:54 -04:00
parent 2253ecc621
commit c665929ae2
5 changed files with 73 additions and 2 deletions

View File

@ -14,6 +14,9 @@
#ifdef ANDROID
# include <android/log.h>
#endif
#ifdef MOZ_WIDGET_ANDROID
# include "APKOpen.h"
#endif
#include <stdio.h>
#include "mozilla/Assertions.h"
@ -26,6 +29,9 @@ mozalloc_abort(const char* const msg)
fputs("\n", stderr);
#else
__android_log_print(ANDROID_LOG_ERROR, "Gecko", "mozalloc_abort: %s", msg);
#endif
#ifdef MOZ_WIDGET_ANDROID
abortThroughJava(msg);
#endif
MOZ_CRASH();
}

View File

@ -531,6 +531,23 @@ public final class GeckoLoader {
}
}
@SuppressWarnings("serial")
public static class AbortException extends Exception {
public AbortException(String msg) {
super(msg);
}
}
@JNITarget
public static void abort(final String msg) {
final Thread thread = Thread.currentThread();
final Thread.UncaughtExceptionHandler uncaughtHandler =
thread.getUncaughtExceptionHandler();
if (uncaughtHandler != null) {
uncaughtHandler.uncaughtException(thread, new AbortException(msg));
}
}
// These methods are implemented in mozglue/android/nsGeckoUtils.cpp
private static native void putenv(String map);

View File

@ -124,6 +124,50 @@ JNI_Throw(JNIEnv* jenv, const char* classname, const char* msg)
jenv->DeleteLocalRef(cls);
}
namespace {
JavaVM* sJavaVM;
}
void
abortThroughJava(const char* msg)
{
struct sigaction sigact = {};
if (SEGVHandler::__wrap_sigaction(SIGSEGV, nullptr, &sigact)) {
return; // sigaction call failed.
}
Dl_info info = {};
if ((sigact.sa_flags & SA_SIGINFO) &&
__wrap_dladdr(reinterpret_cast<void*>(sigact.sa_sigaction), &info) &&
info.dli_fname && strstr(info.dli_fname, "libxul.so")) {
return; // Existing signal handler is in libxul (i.e. we have crash reporter).
}
JNIEnv* env = nullptr;
if (!sJavaVM || sJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr) != JNI_OK) {
return;
}
if (!env || env->PushLocalFrame(2) != JNI_OK) {
return;
}
jclass loader = env->FindClass("org/mozilla/gecko/mozglue/GeckoLoader");
if (!loader) {
return;
}
jmethodID method = env->GetStaticMethodID(loader, "abort", "(Ljava/lang/String;)V");
jstring str = env->NewStringUTF(msg);
if (method && str) {
env->CallStaticVoidMethod(loader, method, str);
}
env->PopLocalFrame(nullptr);
}
#define JNI_STUBS
#include "jni-stubs.inc"
#undef JNI_STUBS
@ -302,6 +346,8 @@ loadNSSLibs(const char *apkName)
extern "C" NS_EXPORT void JNICALL
Java_org_mozilla_gecko_mozglue_GeckoLoader_loadGeckoLibsNative(JNIEnv *jenv, jclass jGeckoAppShellClass, jstring jApkName)
{
jenv->GetJavaVM(&sJavaVM);
const char* str;
// XXX: java doesn't give us true UTF8, we should figure out something
// better to do here

View File

@ -19,6 +19,7 @@ struct mapping_info {
};
NS_EXPORT const struct mapping_info * getLibraryMapping();
NS_EXPORT void abortThroughJava(const char* msg);
static const int SUCCESS = 0;
static const int FAILURE = 1;

View File

@ -327,13 +327,14 @@ public:
return signalHandlingBroken;
}
static int __wrap_sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
protected:
SEGVHandler();
~SEGVHandler();
private:
static int __wrap_sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
/**
* The constructor doesn't do all initialization, and the tail is done