author | Jim Chen <nchen@mozilla.com> |
Wed, 24 Sep 2014 14:12:54 -0400 | |
changeset 207079 | 421c30629ac5bca71a03dead2a7d8889609e188d |
parent 207078 | 4aafc40bcd62ad4e289fa28ed0269ef33e52b399 |
child 207080 | 4cf6c10a0ab9cc18f46f876a86fbe84ec82a5eee |
push id | 27544 |
push user | ryanvm@gmail.com |
push date | Wed, 24 Sep 2014 21:10:36 +0000 |
treeherder | mozilla-central@1735ff2bb23e [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | snorp |
bugs | 1066760 |
milestone | 35.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/memory/mozalloc/mozalloc_abort.cpp +++ b/memory/mozalloc/mozalloc_abort.cpp @@ -9,29 +9,35 @@ # define MOZALLOC_EXPORT __declspec(dllexport) #endif #include "mozilla/mozalloc_abort.h" #ifdef ANDROID # include <android/log.h> #endif +#ifdef MOZ_WIDGET_ANDROID +# include "APKOpen.h" +#endif #include <stdio.h> #include "mozilla/Assertions.h" void mozalloc_abort(const char* const msg) { #ifndef ANDROID fputs(msg, stderr); 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(); } #if defined(XP_UNIX) // Define abort() here, so that it is used instead of the system abort(). This // lets us control the behavior when aborting, in order to get better results // on *NIX platforms. See mozalloc_abort for details. void abort(void)
--- a/mobile/android/base/mozglue/GeckoLoader.java.in +++ b/mobile/android/base/mozglue/GeckoLoader.java.in @@ -526,16 +526,33 @@ public final class GeckoLoader { DecimalFormatSymbols dfs = df.getDecimalFormatSymbols(); putenv("LOCALE_DECIMAL_POINT=" + dfs.getDecimalSeparator()); putenv("LOCALE_THOUSANDS_SEP=" + dfs.getGroupingSeparator()); putenv("LOCALE_GROUPING=" + (char)df.getGroupingSize()); } } + @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); // These methods are implemented in mozglue/android/APKOpen.cpp public static native void nativeRun(String args); private static native void loadGeckoLibsNative(String apkName); private static native void loadSQLiteLibsNative(String apkName); private static native void loadNSSLibsNative(String apkName);
--- a/mozglue/android/APKOpen.cpp +++ b/mozglue/android/APKOpen.cpp @@ -119,16 +119,60 @@ JNI_Throw(JNIEnv* jenv, const char* clas int rc = jenv->ThrowNew(cls, msg); if (rc < 0) { __android_log_print(ANDROID_LOG_ERROR, "GeckoLibLoad", "Error throwing exception %s\n", msg); exit(FAILURE); } 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 static void * xul_handle = nullptr; #ifndef MOZ_FOLD_LIBS static void * sqlite_handle = nullptr; static void * nspr_handle = nullptr; @@ -297,16 +341,18 @@ loadNSSLibs(const char *apkName) #endif return setup_nss_functions(nss_handle, nspr_handle, plc_handle); } 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 str = jenv->GetStringUTFChars(jApkName, nullptr); if (str == nullptr) return; int res = loadGeckoLibs(str);
--- a/mozglue/android/APKOpen.h +++ b/mozglue/android/APKOpen.h @@ -14,14 +14,15 @@ struct mapping_info { char * name; uintptr_t base; size_t len; size_t offset; }; NS_EXPORT const struct mapping_info * getLibraryMapping(); +NS_EXPORT void abortThroughJava(const char* msg); static const int SUCCESS = 0; static const int FAILURE = 1; void JNI_Throw(JNIEnv* jenv, const char* classname, const char* msg); #endif /* APKOpen_h */
--- a/mozglue/linker/ElfLoader.h +++ b/mozglue/linker/ElfLoader.h @@ -322,23 +322,24 @@ public: FinishInitialization(); return registeredHandler; } bool isSignalHandlingBroken() { 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 * at a later time. */ void FinishInitialization(); /**