52 |
#include "target_native_misc.h" |
#include "target_native_misc.h" |
53 |
|
|
54 |
/* Internal functions */ |
/* Internal functions */ |
55 |
static char *copy_string(JNIEnv *env, jobject string); |
static char *copy_string (JNIEnv * env, jobject string); |
56 |
static char *copy_elem(JNIEnv *env, jobject stringArray, jint i); |
static char *copy_elem (JNIEnv * env, jobject stringArray, jint i); |
57 |
|
|
58 |
/* Some O/S's don't declare 'environ' */ |
/* Some O/S's don't declare 'environ' */ |
59 |
#if HAVE_CRT_EXTERNS_H |
#if HAVE_CRT_EXTERNS_H |
70 |
* Internal helper function to copy a String in UTF-8 format. |
* Internal helper function to copy a String in UTF-8 format. |
71 |
*/ |
*/ |
72 |
static char * |
static char * |
73 |
copy_string(JNIEnv *env, jobject string) |
copy_string (JNIEnv * env, jobject string) |
74 |
{ |
{ |
75 |
char errbuf[64]; |
char errbuf[64]; |
76 |
const char *utf; |
const char *utf; |
80 |
/* Check for null */ |
/* Check for null */ |
81 |
if (string == NULL) |
if (string == NULL) |
82 |
{ |
{ |
83 |
clazz = (*env)->FindClass(env, "java/lang/NullPointerException"); |
clazz = (*env)->FindClass (env, "java/lang/NullPointerException"); |
84 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
85 |
return NULL; |
return NULL; |
86 |
(*env)->ThrowNew(env, clazz, NULL); |
(*env)->ThrowNew (env, clazz, NULL); |
87 |
(*env)->DeleteLocalRef(env, clazz); |
(*env)->DeleteLocalRef (env, clazz); |
88 |
return NULL; |
return NULL; |
89 |
} |
} |
90 |
|
|
91 |
/* Extract UTF-8 */ |
/* Extract UTF-8 */ |
92 |
utf = (*env)->GetStringUTFChars(env, string, NULL); |
utf = (*env)->GetStringUTFChars (env, string, NULL); |
93 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
94 |
return NULL; |
return NULL; |
95 |
|
|
96 |
/* Copy it */ |
/* Copy it */ |
97 |
if ((copy = strdup(utf)) == NULL) |
if ((copy = strdup (utf)) == NULL) |
98 |
{ |
{ |
99 |
TARGET_NATIVE_MISC_FORMAT_STRING1(errbuf, sizeof(errbuf), |
TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf, sizeof (errbuf), |
100 |
"strdup: %s", strerror(errno)); |
"strdup: %s", strerror (errno)); |
101 |
clazz = (*env)->FindClass(env, "java/lang/InternalError"); |
clazz = (*env)->FindClass (env, "java/lang/InternalError"); |
102 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
103 |
return NULL; |
return NULL; |
104 |
(*env)->ThrowNew(env, clazz, errbuf); |
(*env)->ThrowNew (env, clazz, errbuf); |
105 |
(*env)->DeleteLocalRef(env, clazz); |
(*env)->DeleteLocalRef (env, clazz); |
106 |
} |
} |
107 |
|
|
108 |
/* Done */ |
/* Done */ |
109 |
(*env)->ReleaseStringUTFChars(env, string, utf); |
(*env)->ReleaseStringUTFChars (env, string, utf); |
110 |
return copy; |
return copy; |
111 |
} |
} |
112 |
|
|
114 |
* Internal helper function to copy a String[] element in UTF-8 format. |
* Internal helper function to copy a String[] element in UTF-8 format. |
115 |
*/ |
*/ |
116 |
static char * |
static char * |
117 |
copy_elem(JNIEnv *env, jobject stringArray, jint i) |
copy_elem (JNIEnv * env, jobject stringArray, jint i) |
118 |
{ |
{ |
119 |
jobject elem; |
jobject elem; |
120 |
char *rtn; |
char *rtn; |
121 |
|
|
122 |
elem = (*env)->GetObjectArrayElement(env, stringArray, i); |
elem = (*env)->GetObjectArrayElement (env, stringArray, i); |
123 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
124 |
return NULL; |
return NULL; |
125 |
if ((rtn = copy_string(env, elem)) == NULL) |
if ((rtn = copy_string (env, elem)) == NULL) |
126 |
return NULL; |
return NULL; |
127 |
(*env)->DeleteLocalRef(env, elem); |
(*env)->DeleteLocalRef (env, elem); |
128 |
return rtn; |
return rtn; |
129 |
} |
} |
130 |
|
|
133 |
* throws java/io/IOException |
* throws java/io/IOException |
134 |
*/ |
*/ |
135 |
JNIEXPORT void JNICALL |
JNIEXPORT void JNICALL |
136 |
Java_java_lang_VMProcess_nativeSpawn(JNIEnv *env, jobject this, |
Java_java_lang_VMProcess_nativeSpawn (JNIEnv * env, jobject this, |
137 |
jobjectArray cmdArray, jobjectArray envArray, jobject dirFile) |
jobjectArray cmdArray, |
138 |
|
jobjectArray envArray, jobject dirFile) |
139 |
{ |
{ |
140 |
int fds[3][2] = { { -1, -1 }, { -1, -1 }, { -1, -1 } }; |
int fds[3][2] = { {-1, -1}, {-1, -1}, {-1, -1} }; |
141 |
jobject streams[3] = { NULL, NULL, NULL }; |
jobject streams[3] = { NULL, NULL, NULL }; |
142 |
jobject dirString = NULL; |
jobject dirString = NULL; |
143 |
char **newEnviron = NULL; |
char **newEnviron = NULL; |
159 |
/* Invoke dirFile.getPath() */ |
/* Invoke dirFile.getPath() */ |
160 |
if (dirFile != NULL) |
if (dirFile != NULL) |
161 |
{ |
{ |
162 |
clazz = (*env)->FindClass(env, "java/io/File"); |
clazz = (*env)->FindClass (env, "java/io/File"); |
163 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
164 |
return; |
return; |
165 |
method = (*env)->GetMethodID(env, |
method = (*env)->GetMethodID (env, |
166 |
clazz, "getPath", "()Ljava/lang/String;"); |
clazz, "getPath", "()Ljava/lang/String;"); |
167 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
168 |
return; |
return; |
169 |
dirString = (*env)->CallObjectMethod(env, dirFile, method); |
dirString = (*env)->CallObjectMethod (env, dirFile, method); |
170 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
171 |
return; |
return; |
172 |
(*env)->DeleteLocalRef(env, clazz); |
(*env)->DeleteLocalRef (env, clazz); |
173 |
} |
} |
174 |
|
|
175 |
/* |
/* |
177 |
* handle the command parameters, the new environment, and the new |
* handle the command parameters, the new environment, and the new |
178 |
* directory into a single array for simplicity of (de)allocation. |
* directory into a single array for simplicity of (de)allocation. |
179 |
*/ |
*/ |
180 |
cmdArrayLen = (*env)->GetArrayLength(env, cmdArray); |
cmdArrayLen = (*env)->GetArrayLength (env, cmdArray); |
181 |
if (cmdArrayLen == 0) |
if (cmdArrayLen == 0) |
182 |
goto null_pointer_exception; |
goto null_pointer_exception; |
183 |
if (envArray != NULL) |
if (envArray != NULL) |
184 |
envArrayLen = (*env)->GetArrayLength(env, envArray); |
envArrayLen = (*env)->GetArrayLength (env, envArray); |
185 |
if ((strings = malloc(((cmdArrayLen + 1) |
if ((strings = malloc (((cmdArrayLen + 1) |
186 |
+ (envArray != NULL ? envArrayLen + 1 : 0) |
+ (envArray != NULL ? envArrayLen + 1 : 0) |
187 |
+ (dirString != NULL ? 1 : 0)) * sizeof(*strings))) == NULL) |
+ (dirString != |
188 |
{ |
NULL ? 1 : 0)) * sizeof (*strings))) == NULL) |
189 |
TARGET_NATIVE_MISC_FORMAT_STRING1(errbuf, |
{ |
190 |
sizeof(errbuf), "malloc: %s", strerror(errno)); |
TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf, |
191 |
|
sizeof (errbuf), "malloc: %s", |
192 |
|
strerror (errno)); |
193 |
goto out_of_memory; |
goto out_of_memory; |
194 |
} |
} |
195 |
|
|
196 |
/* Extract C strings from the various String parameters */ |
/* Extract C strings from the various String parameters */ |
197 |
for (i = 0; i < cmdArrayLen; i++) |
for (i = 0; i < cmdArrayLen; i++) |
198 |
{ |
{ |
199 |
if ((strings[num_strings++] = copy_elem(env, cmdArray, i)) == NULL) |
if ((strings[num_strings++] = copy_elem (env, cmdArray, i)) == NULL) |
200 |
goto done; |
goto done; |
201 |
} |
} |
202 |
strings[num_strings++] = NULL; /* terminate array with NULL */ |
strings[num_strings++] = NULL; /* terminate array with NULL */ |
203 |
if (envArray != NULL) |
if (envArray != NULL) |
204 |
{ |
{ |
205 |
newEnviron = strings + num_strings; |
newEnviron = strings + num_strings; |
206 |
for (i = 0; i < envArrayLen; i++) |
for (i = 0; i < envArrayLen; i++) |
207 |
{ |
{ |
208 |
if ((strings[num_strings++] = copy_elem(env, envArray, i)) == NULL) |
if ((strings[num_strings++] = copy_elem (env, envArray, i)) == NULL) |
209 |
goto done; |
goto done; |
210 |
} |
} |
211 |
strings[num_strings++] = NULL; /* terminate array with NULL */ |
strings[num_strings++] = NULL; /* terminate array with NULL */ |
212 |
} |
} |
213 |
if (dirString != NULL) |
if (dirString != NULL) |
214 |
{ |
{ |
215 |
if ((dir = copy_string(env, dirString)) == NULL) |
if ((dir = copy_string (env, dirString)) == NULL) |
216 |
goto done; |
goto done; |
217 |
strings[num_strings++] = dir; |
strings[num_strings++] = dir; |
218 |
} |
} |
220 |
/* Create inter-process pipes */ |
/* Create inter-process pipes */ |
221 |
for (i = 0; i < 3; i++) |
for (i = 0; i < 3; i++) |
222 |
{ |
{ |
223 |
if (pipe(fds[i]) == -1) |
if (pipe (fds[i]) == -1) |
224 |
{ |
{ |
225 |
TARGET_NATIVE_MISC_FORMAT_STRING1(errbuf, |
TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf, |
226 |
sizeof(errbuf), "pipe: %s", strerror(errno)); |
sizeof (errbuf), "pipe: %s", |
227 |
|
strerror (errno)); |
228 |
goto system_error; |
goto system_error; |
229 |
} |
} |
230 |
} |
} |
231 |
|
|
232 |
/* Set close-on-exec flag for parent's ends of pipes */ |
/* Set close-on-exec flag for parent's ends of pipes */ |
233 |
(void)fcntl(fds[0][1], F_SETFD, 1); |
(void) fcntl (fds[0][1], F_SETFD, 1); |
234 |
(void)fcntl(fds[1][0], F_SETFD, 1); |
(void) fcntl (fds[1][0], F_SETFD, 1); |
235 |
(void)fcntl(fds[2][0], F_SETFD, 1); |
(void) fcntl (fds[2][0], F_SETFD, 1); |
236 |
|
|
237 |
/* Fork into parent and child processes */ |
/* Fork into parent and child processes */ |
238 |
if ((pid = fork()) == (pid_t)-1) |
if ((pid = fork ()) == (pid_t) - 1) |
239 |
{ |
{ |
240 |
TARGET_NATIVE_MISC_FORMAT_STRING1(errbuf, |
TARGET_NATIVE_MISC_FORMAT_STRING1 (errbuf, |
241 |
sizeof(errbuf), "fork: %s", strerror(errno)); |
sizeof (errbuf), "fork: %s", |
242 |
|
strerror (errno)); |
243 |
goto system_error; |
goto system_error; |
244 |
} |
} |
245 |
|
|
251 |
/* Move file descriptors to standard locations */ |
/* Move file descriptors to standard locations */ |
252 |
if (fds[0][0] != 0) |
if (fds[0][0] != 0) |
253 |
{ |
{ |
254 |
if (dup2(fds[0][0], 0) == -1) |
if (dup2 (fds[0][0], 0) == -1) |
255 |
{ |
{ |
256 |
fprintf(stderr, "dup2: %s", strerror(errno)); |
fprintf (stderr, "dup2: %s", strerror (errno)); |
257 |
exit(127); |
exit (127); |
258 |
} |
} |
259 |
close(fds[0][0]); |
close (fds[0][0]); |
260 |
} |
} |
261 |
if (fds[1][1] != 1) |
if (fds[1][1] != 1) |
262 |
{ |
{ |
263 |
if (dup2(fds[1][1], 1) == -1) |
if (dup2 (fds[1][1], 1) == -1) |
264 |
{ |
{ |
265 |
fprintf(stderr, "dup2: %s", strerror(errno)); |
fprintf (stderr, "dup2: %s", strerror (errno)); |
266 |
exit(127); |
exit (127); |
267 |
} |
} |
268 |
close(fds[1][1]); |
close (fds[1][1]); |
269 |
} |
} |
270 |
if (fds[2][1] != 2) |
if (fds[2][1] != 2) |
271 |
{ |
{ |
272 |
if (dup2(fds[2][1], 2) == -1) |
if (dup2 (fds[2][1], 2) == -1) |
273 |
{ |
{ |
274 |
fprintf(stderr, "dup2: %s", strerror(errno)); |
fprintf (stderr, "dup2: %s", strerror (errno)); |
275 |
exit(127); |
exit (127); |
276 |
} |
} |
277 |
close(fds[2][1]); |
close (fds[2][1]); |
278 |
} |
} |
279 |
|
|
280 |
/* Change into destination directory */ |
/* Change into destination directory */ |
281 |
if (dir != NULL && chdir(dir) == -1) |
if (dir != NULL && chdir (dir) == -1) |
282 |
{ |
{ |
283 |
fprintf(stderr, "%s: %s", dir, strerror(errno)); |
fprintf (stderr, "%s: %s", dir, strerror (errno)); |
284 |
exit(127); |
exit (127); |
285 |
} |
} |
286 |
|
|
287 |
/* Make argv[0] last component of executable pathname */ |
/* Make argv[0] last component of executable pathname */ |
288 |
/* XXX should use "file.separator" property here XXX */ |
/* XXX should use "file.separator" property here XXX */ |
289 |
for (i = strlen(path); i > 0 && path[i - 1] != '/'; i--); |
for (i = strlen (path); i > 0 && path[i - 1] != '/'; i--); |
290 |
strings[0] = path + i; |
strings[0] = path + i; |
291 |
|
|
292 |
/* Set new environment */ |
/* Set new environment */ |
294 |
environ = newEnviron; |
environ = newEnviron; |
295 |
|
|
296 |
/* Execute new program (this will close the parent end of the pipes) */ |
/* Execute new program (this will close the parent end of the pipes) */ |
297 |
execvp(path, strings); |
execvp (path, strings); |
298 |
|
|
299 |
/* Failed */ |
/* Failed */ |
300 |
fprintf(stderr, "%s: %s", path, strerror(errno)); |
fprintf (stderr, "%s: %s", path, strerror (errno)); |
301 |
exit(127); |
exit (127); |
302 |
} |
} |
303 |
|
|
304 |
/* Create Input/OutputStream objects around parent file descriptors */ |
/* Create Input/OutputStream objects around parent file descriptors */ |
305 |
clazz = (*env)->FindClass(env, "gnu/java/nio/channels/FileChannelImpl"); |
clazz = (*env)->FindClass (env, "gnu/java/nio/channels/FileChannelImpl"); |
306 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
307 |
goto done; |
goto done; |
308 |
method = (*env)->GetMethodID(env, clazz, "<init>", "(II)V"); |
method = (*env)->GetMethodID (env, clazz, "<init>", "(II)V"); |
309 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
310 |
goto done; |
goto done; |
311 |
for (i = 0; i < 3; i++) |
for (i = 0; i < 3; i++) |
312 |
{ |
{ |
316 |
jclass sclazz; |
jclass sclazz; |
317 |
jmethodID smethod; |
jmethodID smethod; |
318 |
|
|
319 |
jobject channel = (*env)->NewObject(env, clazz, method, fd, mode); |
jobject channel = (*env)->NewObject (env, clazz, method, fd, mode); |
320 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
321 |
goto done; |
goto done; |
322 |
|
|
323 |
if (mode == 2) |
if (mode == 2) |
324 |
sclazz = (*env)->FindClass(env, "java/io/FileOutputStream"); |
sclazz = (*env)->FindClass (env, "java/io/FileOutputStream"); |
325 |
else |
else |
326 |
sclazz = (*env)->FindClass(env, "java/io/FileInputStream"); |
sclazz = (*env)->FindClass (env, "java/io/FileInputStream"); |
327 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
328 |
goto done; |
goto done; |
329 |
|
|
330 |
smethod = (*env)->GetMethodID(env, sclazz, "<init>", |
smethod = (*env)->GetMethodID (env, sclazz, "<init>", |
331 |
"(Lgnu/java/nio/channels/FileChannelImpl;)V"); |
"(Lgnu/java/nio/channels/FileChannelImpl;)V"); |
332 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
333 |
goto done; |
goto done; |
334 |
|
|
335 |
streams[i] = (*env)->NewObject(env, sclazz, smethod, channel); |
streams[i] = (*env)->NewObject (env, sclazz, smethod, channel); |
336 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
337 |
goto done; |
goto done; |
338 |
|
|
339 |
(*env)->DeleteLocalRef(env, sclazz); |
(*env)->DeleteLocalRef (env, sclazz); |
340 |
} |
} |
341 |
(*env)->DeleteLocalRef(env, clazz); |
(*env)->DeleteLocalRef (env, clazz); |
342 |
|
|
343 |
/* Invoke VMProcess.setProcessInfo() to update VMProcess object */ |
/* Invoke VMProcess.setProcessInfo() to update VMProcess object */ |
344 |
method = (*env)->GetMethodID(env, |
method = (*env)->GetMethodID (env, |
345 |
(*env)->GetObjectClass(env, this), "setProcessInfo", |
(*env)->GetObjectClass (env, this), |
346 |
"(Ljava/io/OutputStream;Ljava/io/InputStream;Ljava/io/InputStream;J)V"); |
"setProcessInfo", |
347 |
if ((*env)->ExceptionOccurred(env)) |
"(Ljava/io/OutputStream;Ljava/io/InputStream;Ljava/io/InputStream;J)V"); |
348 |
|
if ((*env)->ExceptionOccurred (env)) |
349 |
goto done; |
goto done; |
350 |
(*env)->CallVoidMethod(env, this, method, |
(*env)->CallVoidMethod (env, this, method, |
351 |
streams[0], streams[1], streams[2], (jlong)pid); |
streams[0], streams[1], streams[2], (jlong) pid); |
352 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
353 |
goto done; |
goto done; |
354 |
(*env)->DeleteLocalRef(env, clazz); |
(*env)->DeleteLocalRef (env, clazz); |
355 |
|
|
356 |
done: |
done: |
357 |
/* |
/* |
365 |
const int fd = fds[i][i != 0]; |
const int fd = fds[i][i != 0]; |
366 |
|
|
367 |
if (fd != -1) |
if (fd != -1) |
368 |
close(fd); |
close (fd); |
369 |
} |
} |
370 |
|
|
371 |
/* |
/* |
379 |
const int fd = fds[i][i == 0]; |
const int fd = fds[i][i == 0]; |
380 |
|
|
381 |
if (fd != -1 && streams[i] == NULL) |
if (fd != -1 && streams[i] == NULL) |
382 |
close(fd); |
close (fd); |
383 |
} |
} |
384 |
|
|
385 |
/* Free C strings */ |
/* Free C strings */ |
386 |
while (num_strings > 0) |
while (num_strings > 0) |
387 |
free(strings[--num_strings]); |
free (strings[--num_strings]); |
388 |
free(strings); |
free (strings); |
389 |
|
|
390 |
/* Done */ |
/* Done */ |
391 |
return; |
return; |
392 |
|
|
393 |
null_pointer_exception: |
null_pointer_exception: |
394 |
clazz = (*env)->FindClass(env, "java/lang/NullPointerException"); |
clazz = (*env)->FindClass (env, "java/lang/NullPointerException"); |
395 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
396 |
goto done; |
goto done; |
397 |
(*env)->ThrowNew(env, clazz, NULL); |
(*env)->ThrowNew (env, clazz, NULL); |
398 |
(*env)->DeleteLocalRef(env, clazz); |
(*env)->DeleteLocalRef (env, clazz); |
399 |
goto done; |
goto done; |
400 |
|
|
401 |
out_of_memory: |
out_of_memory: |
402 |
clazz = (*env)->FindClass(env, "java/lang/InternalError"); |
clazz = (*env)->FindClass (env, "java/lang/InternalError"); |
403 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
404 |
goto done; |
goto done; |
405 |
(*env)->ThrowNew(env, clazz, errbuf); |
(*env)->ThrowNew (env, clazz, errbuf); |
406 |
(*env)->DeleteLocalRef(env, clazz); |
(*env)->DeleteLocalRef (env, clazz); |
407 |
goto done; |
goto done; |
408 |
|
|
409 |
system_error: |
system_error: |
410 |
clazz = (*env)->FindClass(env, "java/io/IOException"); |
clazz = (*env)->FindClass (env, "java/io/IOException"); |
411 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
412 |
goto done; |
goto done; |
413 |
(*env)->ThrowNew(env, clazz, errbuf); |
(*env)->ThrowNew (env, clazz, errbuf); |
414 |
(*env)->DeleteLocalRef(env, clazz); |
(*env)->DeleteLocalRef (env, clazz); |
415 |
goto done; |
goto done; |
416 |
} |
} |
417 |
|
|
419 |
* private static final native boolean nativeReap() |
* private static final native boolean nativeReap() |
420 |
*/ |
*/ |
421 |
JNIEXPORT jboolean JNICALL |
JNIEXPORT jboolean JNICALL |
422 |
Java_java_lang_VMProcess_nativeReap(JNIEnv *env, jclass clazz) |
Java_java_lang_VMProcess_nativeReap (JNIEnv * env, jclass clazz) |
423 |
{ |
{ |
424 |
char ebuf[64]; |
char ebuf[64]; |
425 |
jfieldID field; |
jfieldID field; |
427 |
pid_t pid; |
pid_t pid; |
428 |
|
|
429 |
/* Try to reap a child process, but don't block */ |
/* Try to reap a child process, but don't block */ |
430 |
if ((pid = waitpid((pid_t)-1, &status, WNOHANG)) == 0) |
if ((pid = waitpid ((pid_t) - 1, &status, WNOHANG)) == 0) |
431 |
return JNI_FALSE; |
return JNI_FALSE; |
432 |
|
|
433 |
/* Check result from waitpid() */ |
/* Check result from waitpid() */ |
434 |
if (pid == (pid_t)-1) |
if (pid == (pid_t) - 1) |
435 |
{ |
{ |
436 |
if (errno == ECHILD || errno == EINTR) |
if (errno == ECHILD || errno == EINTR) |
437 |
return JNI_FALSE; |
return JNI_FALSE; |
438 |
TARGET_NATIVE_MISC_FORMAT_STRING2(ebuf, |
TARGET_NATIVE_MISC_FORMAT_STRING2 (ebuf, |
439 |
sizeof(ebuf), "waitpid(%ld): %s", (long)pid, strerror(errno)); |
sizeof (ebuf), "waitpid(%ld): %s", |
440 |
clazz = (*env)->FindClass(env, "java/lang/InternalError"); |
(long) pid, strerror (errno)); |
441 |
if ((*env)->ExceptionOccurred(env)) |
clazz = (*env)->FindClass (env, "java/lang/InternalError"); |
442 |
|
if ((*env)->ExceptionOccurred (env)) |
443 |
return JNI_FALSE; |
return JNI_FALSE; |
444 |
(*env)->ThrowNew(env, clazz, ebuf); |
(*env)->ThrowNew (env, clazz, ebuf); |
445 |
(*env)->DeleteLocalRef(env, clazz); |
(*env)->DeleteLocalRef (env, clazz); |
446 |
return JNI_FALSE; |
return JNI_FALSE; |
447 |
} |
} |
448 |
|
|
449 |
/* Get exit code; for signal termination return negative signal value XXX */ |
/* Get exit code; for signal termination return negative signal value XXX */ |
450 |
if (WIFEXITED(status)) |
if (WIFEXITED (status)) |
451 |
status = (jint)(jbyte)WEXITSTATUS(status); |
status = (jint) (jbyte) WEXITSTATUS (status); |
452 |
else if (WIFSIGNALED(status)) |
else if (WIFSIGNALED (status)) |
453 |
status = -(jint)WTERMSIG(status); |
status = -(jint) WTERMSIG (status); |
454 |
else |
else |
455 |
return JNI_FALSE; /* process merely stopped; ignore */ |
return JNI_FALSE; /* process merely stopped; ignore */ |
456 |
|
|
457 |
/* Return process pid and exit status */ |
/* Return process pid and exit status */ |
458 |
field = (*env)->GetStaticFieldID(env, clazz, "reapedPid", "J"); |
field = (*env)->GetStaticFieldID (env, clazz, "reapedPid", "J"); |
459 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
460 |
return JNI_FALSE; |
return JNI_FALSE; |
461 |
(*env)->SetStaticLongField(env, clazz, field, (jlong)pid); |
(*env)->SetStaticLongField (env, clazz, field, (jlong) pid); |
462 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
463 |
return JNI_FALSE; |
return JNI_FALSE; |
464 |
field = (*env)->GetStaticFieldID(env, clazz, "reapedExitValue", "I"); |
field = (*env)->GetStaticFieldID (env, clazz, "reapedExitValue", "I"); |
465 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
466 |
return JNI_FALSE; |
return JNI_FALSE; |
467 |
(*env)->SetStaticIntField(env, clazz, field, status); |
(*env)->SetStaticIntField (env, clazz, field, status); |
468 |
if ((*env)->ExceptionOccurred(env)) |
if ((*env)->ExceptionOccurred (env)) |
469 |
return JNI_FALSE; |
return JNI_FALSE; |
470 |
|
|
471 |
/* Done */ |
/* Done */ |
476 |
* private static final native void nativeKill(long) |
* private static final native void nativeKill(long) |
477 |
*/ |
*/ |
478 |
JNIEXPORT void JNICALL |
JNIEXPORT void JNICALL |
479 |
Java_java_lang_VMProcess_nativeKill(JNIEnv *env, jclass clazz, jlong pid) |
Java_java_lang_VMProcess_nativeKill (JNIEnv * env, jclass clazz, jlong pid) |
480 |
{ |
{ |
481 |
char ebuf[64]; |
char ebuf[64]; |
482 |
|
|
483 |
if (kill((pid_t)pid, SIGKILL) == -1) |
if (kill ((pid_t) pid, SIGKILL) == -1) |
484 |
{ |
{ |
485 |
TARGET_NATIVE_MISC_FORMAT_STRING2(ebuf, |
TARGET_NATIVE_MISC_FORMAT_STRING2 (ebuf, |
486 |
sizeof(ebuf), "kill(%ld): %s", (long)pid, strerror(errno)); |
sizeof (ebuf), "kill(%ld): %s", |
487 |
clazz = (*env)->FindClass(env, "java/lang/InternalError"); |
(long) pid, strerror (errno)); |
488 |
if ((*env)->ExceptionOccurred(env)) |
clazz = (*env)->FindClass (env, "java/lang/InternalError"); |
489 |
|
if ((*env)->ExceptionOccurred (env)) |
490 |
return; |
return; |
491 |
(*env)->ThrowNew(env, clazz, ebuf); |
(*env)->ThrowNew (env, clazz, ebuf); |
492 |
(*env)->DeleteLocalRef(env, clazz); |
(*env)->DeleteLocalRef (env, clazz); |
493 |
} |
} |
494 |
} |
} |
|
|
|