Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/PojavLauncher
Path: blob/v3_openjdk/app_pojavlauncher/src/main/jni/jre_launcher.c
2128 views
1
/*
2
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
#include <android/log.h>
26
#include <dlfcn.h>
27
#include <errno.h>
28
#include <jni.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <pthread.h>
32
#include <unistd.h>
33
// Boardwalk: missing include
34
#include <string.h>
35
36
#include "log.h"
37
#include "utils.h"
38
#include "environ/environ.h"
39
40
// Uncomment to try redirect signal handling to JVM
41
// #define TRY_SIG2JVM
42
43
// PojavLancher: fixme: are these wrong?
44
#define FULL_VERSION "1.8.0-internal"
45
#define DOT_VERSION "1.8"
46
47
static const char* const_progname = "java";
48
static const char* const_launcher = "openjdk";
49
static const char** const_jargs = NULL;
50
static const char** const_appclasspath = NULL;
51
static const jboolean const_javaw = JNI_FALSE;
52
static const jboolean const_cpwildcard = JNI_TRUE;
53
static const jint const_ergo_class = 0; // DEFAULT_POLICY
54
55
typedef jint JLI_Launch_func(int argc, char ** argv, /* main argc, argc */
56
int jargc, const char** jargv, /* java args */
57
int appclassc, const char** appclassv, /* app classpath */
58
const char* fullversion, /* full version defined */
59
const char* dotversion, /* dot version defined */
60
const char* pname, /* program name */
61
const char* lname, /* launcher name */
62
jboolean javaargs, /* JAVA_ARGS */
63
jboolean cpwildcard, /* classpath wildcard*/
64
jboolean javaw, /* windows-only javaw */
65
jint ergo /* ergonomics class policy */
66
);
67
68
struct {
69
sigset_t tracked_sigset;
70
int pipe[2];
71
} abort_waiter_data;
72
73
_Noreturn extern void nominal_exit(int code, bool is_signal);
74
75
_Noreturn static void* abort_waiter_thread(void* extraArg) {
76
// Don't allow this thread to receive signals this thread is tracking.
77
// We should only receive them externally.
78
pthread_sigmask(SIG_BLOCK, &abort_waiter_data.tracked_sigset, NULL);
79
int signal;
80
// Block for reading the signal ID until it arrives
81
read(abort_waiter_data.pipe[0], &signal, sizeof(int));
82
// Die
83
nominal_exit(signal, true);
84
}
85
86
_Noreturn static void abort_waiter_handler(int signal) {
87
// Write the final signal into the pipe and block forever.
88
write(abort_waiter_data.pipe[1], &signal, sizeof(int));
89
while(1) {}
90
}
91
92
static void abort_waiter_setup() {
93
// Only abort on SIGABRT as the JVM either emits SIGABRT or SIGKILL (which we can't catch)
94
// when a fatal crash occurs. Still, keep expandability if we would want to add more
95
// user-friendly fatal signals in the future.
96
const static int tracked_signals[] = {SIGABRT};
97
const static int ntracked = (sizeof(tracked_signals) / sizeof(tracked_signals[0]));
98
struct sigaction sigactions[ntracked];
99
sigemptyset(&abort_waiter_data.tracked_sigset);
100
for(size_t i = 0; i < ntracked; i++) {
101
sigaddset(&abort_waiter_data.tracked_sigset, tracked_signals[i]);
102
sigactions[i].sa_handler = abort_waiter_handler;
103
}
104
if(pipe(abort_waiter_data.pipe) != 0) {
105
printf("Failed to set up aborter pipe: %s\n", strerror(errno));
106
return;
107
}
108
pthread_t waiter_thread; int result;
109
if((result = pthread_create(&waiter_thread, NULL, abort_waiter_thread, NULL)) != 0) {
110
printf("Failed to start up waiter thread: %s", strerror(result));
111
for(int i = 0; i < 2; i++) close(abort_waiter_data.pipe[i]);
112
return;
113
}
114
// Only set the sigactions *after* we have already set up the pipe and the thread.
115
for(size_t i = 0; i < ntracked; i++) {
116
if(sigaction(tracked_signals[i], &sigactions[i], NULL) != 0) {
117
// Not returning here because we may have set some handlers successfully.
118
// Some handling is better than no handling.
119
printf("Failed to set signal hander for signal %i: %s", i, strerror(errno));
120
}
121
}
122
}
123
124
static jint launchJVM(int margc, char** margv) {
125
void* libjli = dlopen("libjli.so", RTLD_LAZY | RTLD_GLOBAL);
126
127
// Unset all signal handlers to create a good slate for JVM signal detection.
128
struct sigaction clean_sa;
129
memset(&clean_sa, 0, sizeof (struct sigaction));
130
for(int sigid = SIGHUP; sigid < NSIG; sigid++) {
131
// For some reason Android specifically checks if you set SIGSEGV to SIG_DFL.
132
// There's probably a good reason for that but the signal handler here is
133
// temporary and will be replaced by the Java VM's signal/crash handler.
134
// Work around the warning by using SIG_IGN for SIGSEGV
135
if(sigid == SIGSEGV) clean_sa.sa_handler = SIG_IGN;
136
else clean_sa.sa_handler = SIG_DFL;
137
sigaction(sigid, &clean_sa, NULL);
138
}
139
// Set up the thread that will abort the launcher with an user-facing dialog on a signal.
140
abort_waiter_setup();
141
142
// Boardwalk: silence
143
// LOGD("JLI lib = %x", (int)libjli);
144
if (NULL == libjli) {
145
LOGE("JLI lib = NULL: %s", dlerror());
146
return -1;
147
}
148
LOGD("Found JLI lib");
149
150
JLI_Launch_func *pJLI_Launch =
151
(JLI_Launch_func *)dlsym(libjli, "JLI_Launch");
152
// Boardwalk: silence
153
// LOGD("JLI_Launch = 0x%x", *(int*)&pJLI_Launch);
154
155
if (NULL == pJLI_Launch) {
156
LOGE("JLI_Launch = NULL");
157
return -1;
158
}
159
160
LOGD("Calling JLI_Launch");
161
162
return pJLI_Launch(margc, margv,
163
0, NULL, // sizeof(const_jargs) / sizeof(char *), const_jargs,
164
0, NULL, // sizeof(const_appclasspath) / sizeof(char *), const_appclasspath,
165
FULL_VERSION,
166
DOT_VERSION,
167
*margv, // (const_progname != NULL) ? const_progname : *margv,
168
*margv, // (const_launcher != NULL) ? const_launcher : *margv,
169
(const_jargs != NULL) ? JNI_TRUE : JNI_FALSE,
170
const_cpwildcard, const_javaw, const_ergo_class);
171
/*
172
return pJLI_Launch(argc, argv,
173
0, NULL, 0, NULL, FULL_VERSION,
174
DOT_VERSION, *margv, *margv, // "java", "openjdk",
175
JNI_FALSE, JNI_TRUE, JNI_FALSE, 0);
176
*/
177
}
178
179
/*
180
* Class: com_oracle_dalvik_VMLauncher
181
* Method: launchJVM
182
* Signature: ([Ljava/lang/String;)I
183
*/
184
JNIEXPORT jint JNICALL Java_com_oracle_dalvik_VMLauncher_launchJVM(JNIEnv *env, jclass clazz, jobjectArray argsArray) {
185
186
jint res = 0;
187
188
if (argsArray == NULL) {
189
LOGE("Args array null, returning");
190
//handle error
191
return 0;
192
}
193
194
int argc = (*env)->GetArrayLength(env, argsArray);
195
char **argv = convert_to_char_array(env, argsArray);
196
197
LOGD("Done processing args");
198
199
res = launchJVM(argc, argv);
200
201
LOGD("Going to free args");
202
free_char_array(env, argsArray, argv);
203
204
LOGD("Free done");
205
206
return res;
207
}
208
209