diff --git a/src/main/jni/jre_launcher.c b/src/main/jni/jre_launcher.c index 2f0761cc..71f1fcbf 100644 --- a/src/main/jni/jre_launcher.c +++ b/src/main/jni/jre_launcher.c @@ -48,6 +48,27 @@ static const char** const_appclasspath = NULL; static const jboolean const_javaw = JNI_FALSE; static const jboolean const_cpwildcard = JNI_TRUE; static const jint const_ergo_class = 0; // DEFAULT_POLICY +static struct sigaction old_sa[NSIG]; + +void (*__old_sa)(int signal, siginfo_t *info, void *reserved); +int (*sigaction_p) (int signum, + const struct sigaction *_Nullable restrict act, + struct sigaction *_Nullable restrict oldact); +int (*JVM_handle_linux_signal)(int signo, siginfo_t* siginfo, void* ucontext, int abort_if_unrecognized); + +void android_sigaction(int signal, siginfo_t *info, void *reserved) { + if (JVM_handle_linux_signal == NULL) { // should not happen, but still + __old_sa = old_sa[signal].sa_sigaction; + __old_sa(signal,info,reserved); + exit(1); + } else { + // Based on https://github.com/PojavLauncherTeam/openjdk-multiarch-jdk8u/blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/os/linux/vm/os_linux.cpp#L4688-4693 + int orig_errno = errno; // Preserve errno value over signal handler. + JVM_handle_linux_signal(signal, info, reserved, true); + errno = orig_errno; + } +} +typedef jint JNI_CreateJavaVM_func(JavaVM **pvm, void **penv, void *args); typedef jint JLI_Launch_func(int argc, char ** argv, /* main argc, argc */ int jargc, const char** jargv, /* java args */ @@ -65,19 +86,6 @@ typedef jint JLI_Launch_func(int argc, char ** argv, /* main argc, argc */ static jint launchJVM(int margc, char** margv) { void* libjli = dlopen("libjli.so", RTLD_LAZY | RTLD_GLOBAL); - // Unset all signal handlers to create a good slate for JVM signal detection. - struct sigaction clean_sa; - memset(&clean_sa, 0, sizeof (struct sigaction)); - for(int sigid = SIGHUP; sigid < NSIG; sigid++) { - // For some reason Android specifically checks if you set SIGSEGV to SIG_DFL. - // There's probably a good reason for that but the signal handler here is - // temporary and will be replaced by the Java VM's signal/crash handler. - // Work around the warning by using SIG_IGN for SIGSEGV - if(sigid == SIGSEGV) clean_sa.sa_handler = SIG_IGN; - else clean_sa.sa_handler = SIG_DFL; - sigaction(sigid, &clean_sa, NULL); - } - // Boardwalk: silence // LOGD("JLI lib = %x", (int)libjli); if (NULL == libjli) { @@ -115,7 +123,42 @@ static jint launchJVM(int margc, char** margv) { * Signature: ([Ljava/lang/String;)I */ JNIEXPORT jint JNICALL Java_com_oracle_dalvik_VMLauncher_launchJVM(JNIEnv *env, jclass clazz, jobjectArray argsArray) { +#ifdef TRY_SIG2JVM + void* libjsig = dlopen("libjsig.so", RTLD_LAZY | RTLD_GLOBAL); + if (NULL == libjsig) { + LOGE("JSig lib = NULL: %s", dlerror()); + return -1; + } + sigaction_p = (void*) dlsym(libjsig, "sigaction"); + + void* libjvm = dlopen("libjvm.so", RTLD_LAZY | RTLD_GLOBAL); + if (NULL == libjvm) { + LOGE("JVM lib = NULL: %s", dlerror()); + return -1; + } + JVM_handle_linux_signal = dlsym(libjvm, "JVM_handle_linux_signal"); +#endif + jint res = 0; + // int i; + //Prepare the signal trapper + struct sigaction catcher; + memset(&catcher,0,sizeof(sigaction)); + catcher.sa_sigaction = android_sigaction; + catcher.sa_flags = SA_SIGINFO|SA_RESTART; + // SA_RESETHAND; +#define CATCHSIG(X) sigaction_p(X, &catcher, &old_sa[X]) + CATCHSIG(SIGILL); + CATCHSIG(SIGABRT); + CATCHSIG(SIGBUS); + CATCHSIG(SIGFPE); +#ifdef TRY_SIG2JVM + CATCHSIG(SIGSEGV); +#endif + CATCHSIG(SIGSTKFLT); + CATCHSIG(SIGPIPE); + CATCHSIG(SIGXFSZ); + //Signal trapper ready // Save dalvik JNIEnv pointer for JVM launch thread dalvikJNIEnvPtr_ANDROID = env;