Path: blob/v3_openjdk/app_pojavlauncher/src/main/jni/jre_launcher.c
2128 views
/*1* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24#include <android/log.h>25#include <dlfcn.h>26#include <errno.h>27#include <jni.h>28#include <stdio.h>29#include <stdlib.h>30#include <pthread.h>31#include <unistd.h>32// Boardwalk: missing include33#include <string.h>3435#include "log.h"36#include "utils.h"37#include "environ/environ.h"3839// Uncomment to try redirect signal handling to JVM40// #define TRY_SIG2JVM4142// PojavLancher: fixme: are these wrong?43#define FULL_VERSION "1.8.0-internal"44#define DOT_VERSION "1.8"4546static const char* const_progname = "java";47static const char* const_launcher = "openjdk";48static const char** const_jargs = NULL;49static const char** const_appclasspath = NULL;50static const jboolean const_javaw = JNI_FALSE;51static const jboolean const_cpwildcard = JNI_TRUE;52static const jint const_ergo_class = 0; // DEFAULT_POLICY5354typedef jint JLI_Launch_func(int argc, char ** argv, /* main argc, argc */55int jargc, const char** jargv, /* java args */56int appclassc, const char** appclassv, /* app classpath */57const char* fullversion, /* full version defined */58const char* dotversion, /* dot version defined */59const char* pname, /* program name */60const char* lname, /* launcher name */61jboolean javaargs, /* JAVA_ARGS */62jboolean cpwildcard, /* classpath wildcard*/63jboolean javaw, /* windows-only javaw */64jint ergo /* ergonomics class policy */65);6667struct {68sigset_t tracked_sigset;69int pipe[2];70} abort_waiter_data;7172_Noreturn extern void nominal_exit(int code, bool is_signal);7374_Noreturn static void* abort_waiter_thread(void* extraArg) {75// Don't allow this thread to receive signals this thread is tracking.76// We should only receive them externally.77pthread_sigmask(SIG_BLOCK, &abort_waiter_data.tracked_sigset, NULL);78int signal;79// Block for reading the signal ID until it arrives80read(abort_waiter_data.pipe[0], &signal, sizeof(int));81// Die82nominal_exit(signal, true);83}8485_Noreturn static void abort_waiter_handler(int signal) {86// Write the final signal into the pipe and block forever.87write(abort_waiter_data.pipe[1], &signal, sizeof(int));88while(1) {}89}9091static void abort_waiter_setup() {92// Only abort on SIGABRT as the JVM either emits SIGABRT or SIGKILL (which we can't catch)93// when a fatal crash occurs. Still, keep expandability if we would want to add more94// user-friendly fatal signals in the future.95const static int tracked_signals[] = {SIGABRT};96const static int ntracked = (sizeof(tracked_signals) / sizeof(tracked_signals[0]));97struct sigaction sigactions[ntracked];98sigemptyset(&abort_waiter_data.tracked_sigset);99for(size_t i = 0; i < ntracked; i++) {100sigaddset(&abort_waiter_data.tracked_sigset, tracked_signals[i]);101sigactions[i].sa_handler = abort_waiter_handler;102}103if(pipe(abort_waiter_data.pipe) != 0) {104printf("Failed to set up aborter pipe: %s\n", strerror(errno));105return;106}107pthread_t waiter_thread; int result;108if((result = pthread_create(&waiter_thread, NULL, abort_waiter_thread, NULL)) != 0) {109printf("Failed to start up waiter thread: %s", strerror(result));110for(int i = 0; i < 2; i++) close(abort_waiter_data.pipe[i]);111return;112}113// Only set the sigactions *after* we have already set up the pipe and the thread.114for(size_t i = 0; i < ntracked; i++) {115if(sigaction(tracked_signals[i], &sigactions[i], NULL) != 0) {116// Not returning here because we may have set some handlers successfully.117// Some handling is better than no handling.118printf("Failed to set signal hander for signal %i: %s", i, strerror(errno));119}120}121}122123static jint launchJVM(int margc, char** margv) {124void* libjli = dlopen("libjli.so", RTLD_LAZY | RTLD_GLOBAL);125126// Unset all signal handlers to create a good slate for JVM signal detection.127struct sigaction clean_sa;128memset(&clean_sa, 0, sizeof (struct sigaction));129for(int sigid = SIGHUP; sigid < NSIG; sigid++) {130// For some reason Android specifically checks if you set SIGSEGV to SIG_DFL.131// There's probably a good reason for that but the signal handler here is132// temporary and will be replaced by the Java VM's signal/crash handler.133// Work around the warning by using SIG_IGN for SIGSEGV134if(sigid == SIGSEGV) clean_sa.sa_handler = SIG_IGN;135else clean_sa.sa_handler = SIG_DFL;136sigaction(sigid, &clean_sa, NULL);137}138// Set up the thread that will abort the launcher with an user-facing dialog on a signal.139abort_waiter_setup();140141// Boardwalk: silence142// LOGD("JLI lib = %x", (int)libjli);143if (NULL == libjli) {144LOGE("JLI lib = NULL: %s", dlerror());145return -1;146}147LOGD("Found JLI lib");148149JLI_Launch_func *pJLI_Launch =150(JLI_Launch_func *)dlsym(libjli, "JLI_Launch");151// Boardwalk: silence152// LOGD("JLI_Launch = 0x%x", *(int*)&pJLI_Launch);153154if (NULL == pJLI_Launch) {155LOGE("JLI_Launch = NULL");156return -1;157}158159LOGD("Calling JLI_Launch");160161return pJLI_Launch(margc, margv,1620, NULL, // sizeof(const_jargs) / sizeof(char *), const_jargs,1630, NULL, // sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,164FULL_VERSION,165DOT_VERSION,166*margv, // (const_progname != NULL) ? const_progname : *margv,167*margv, // (const_launcher != NULL) ? const_launcher : *margv,168(const_jargs != NULL) ? JNI_TRUE : JNI_FALSE,169const_cpwildcard, const_javaw, const_ergo_class);170/*171return pJLI_Launch(argc, argv,1720, NULL, 0, NULL, FULL_VERSION,173DOT_VERSION, *margv, *margv, // "java", "openjdk",174JNI_FALSE, JNI_TRUE, JNI_FALSE, 0);175*/176}177178/*179* Class: com_oracle_dalvik_VMLauncher180* Method: launchJVM181* Signature: ([Ljava/lang/String;)I182*/183JNIEXPORT jint JNICALL Java_com_oracle_dalvik_VMLauncher_launchJVM(JNIEnv *env, jclass clazz, jobjectArray argsArray) {184185jint res = 0;186187if (argsArray == NULL) {188LOGE("Args array null, returning");189//handle error190return 0;191}192193int argc = (*env)->GetArrayLength(env, argsArray);194char **argv = convert_to_char_array(env, argsArray);195196LOGD("Done processing args");197198res = launchJVM(argc, argv);199200LOGD("Going to free args");201free_char_array(env, argsArray, argv);202203LOGD("Free done");204205return res;206}207208209