Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c
+++ new/jdk/src/java.base/unix/native/libjava/ProcessImpl_md.c
1 1 /*
2 2 * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation. Oracle designates this
8 8 * particular file as subject to the "Classpath" exception as provided
9 9 * by Oracle in the LICENSE file that accompanied this code.
10 10 *
11 11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 14 * version 2 for more details (a copy is included in the LICENSE file that
15 15 * accompanied this code).
16 16 *
17 17 * You should have received a copy of the GNU General Public License version
18 18 * 2 along with this work; if not, write to the Free Software Foundation,
19 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 20 *
21 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 22 * or visit www.oracle.com if you need additional information or have any
23 23 * questions.
24 24 */
25 25
26 26 #undef _LARGEFILE64_SOURCE
27 27 #define _LARGEFILE64_SOURCE 1
28 28
29 29 #include "jni.h"
30 30 #include "jvm.h"
31 31 #include "jvm_md.h"
32 32 #include "jni_util.h"
33 33 #include "io_util.h"
34 34
35 35 /*
36 36 * Platform-specific support for java.lang.Process
37 37 */
38 38 #include <assert.h>
39 39 #include <stddef.h>
40 40 #include <stdlib.h>
41 41 #include <sys/types.h>
42 42 #include <ctype.h>
43 43 #include <sys/wait.h>
44 44 #include <signal.h>
45 45 #include <string.h>
46 46
47 47 #if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
48 48 #include <spawn.h>
49 49 #endif
50 50
51 51 #include "childproc.h"
52 52
53 53 /*
54 54 * There are 4 possible strategies we might use to "fork":
55 55 *
56 56 * - fork(2). Very portable and reliable but subject to
57 57 * failure due to overcommit (see the documentation on
58 58 * /proc/sys/vm/overcommit_memory in Linux proc(5)).
59 59 * This is the ancient problem of spurious failure whenever a large
60 60 * process starts a small subprocess.
61 61 *
62 62 * - vfork(). Using this is scary because all relevant man pages
63 63 * contain dire warnings, e.g. Linux vfork(2). But at least it's
64 64 * documented in the glibc docs and is standardized by XPG4.
65 65 * http://www.opengroup.org/onlinepubs/000095399/functions/vfork.html
66 66 * On Linux, one might think that vfork() would be implemented using
67 67 * the clone system call with flag CLONE_VFORK, but in fact vfork is
68 68 * a separate system call (which is a good sign, suggesting that
69 69 * vfork will continue to be supported at least on Linux).
70 70 * Another good sign is that glibc implements posix_spawn using
71 71 * vfork whenever possible. Note that we cannot use posix_spawn
72 72 * ourselves because there's no reliable way to close all inherited
73 73 * file descriptors.
74 74 *
75 75 * - clone() with flags CLONE_VM but not CLONE_THREAD. clone() is
76 76 * Linux-specific, but this ought to work - at least the glibc
77 77 * sources contain code to handle different combinations of CLONE_VM
78 78 * and CLONE_THREAD. However, when this was implemented, it
79 79 * appeared to fail on 32-bit i386 (but not 64-bit x86_64) Linux with
80 80 * the simple program
81 81 * Runtime.getRuntime().exec("/bin/true").waitFor();
82 82 * with:
83 83 * # Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536
84 84 * # Error: pthread_getattr_np failed with errno = 3 (ESRCH)
85 85 * We believe this is a glibc bug, reported here:
86 86 * http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311
87 87 * but the glibc maintainers closed it as WONTFIX.
88 88 *
89 89 * - posix_spawn(). While posix_spawn() is a fairly elaborate and
90 90 * complicated system call, it can't quite do everything that the old
91 91 * fork()/exec() combination can do, so the only feasible way to do
92 92 * this, is to use posix_spawn to launch a new helper executable
93 93 * "jprochelper", which in turn execs the target (after cleaning
94 94 * up file-descriptors etc.) The end result is the same as before,
95 95 * a child process linked to the parent in the same way, but it
96 96 * avoids the problem of duplicating the parent (VM) process
97 97 * address space temporarily, before launching the target command.
98 98 *
99 99 * Based on the above analysis, we are currently using vfork() on
100 100 * Linux and posix_spawn() on other Unix systems.
101 101 */
102 102
103 103
104 104 static void
105 105 setSIGCHLDHandler(JNIEnv *env)
106 106 {
107 107 /* There is a subtle difference between having the signal handler
108 108 * for SIGCHLD be SIG_DFL and SIG_IGN. We cannot obtain process
109 109 * termination information for child processes if the signal
110 110 * handler is SIG_IGN. It must be SIG_DFL.
111 111 *
112 112 * We used to set the SIGCHLD handler only on Linux, but it's
113 113 * safest to set it unconditionally.
114 114 *
115 115 * Consider what happens if java's parent process sets the SIGCHLD
116 116 * handler to SIG_IGN. Normally signal handlers are inherited by
117 117 * children, but SIGCHLD is a controversial case. Solaris appears
118 118 * to always reset it to SIG_DFL, but this behavior may be
119 119 * non-standard-compliant, and we shouldn't rely on it.
120 120 *
121 121 * References:
122 122 * http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html
123 123 * http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html
124 124 */
125 125 struct sigaction sa;
126 126 sa.sa_handler = SIG_DFL;
127 127 sigemptyset(&sa.sa_mask);
128 128 sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
129 129 if (sigaction(SIGCHLD, &sa, NULL) < 0)
130 130 JNU_ThrowInternalError(env, "Can't set SIGCHLD handler");
131 131 }
132 132
133 133 static void*
134 134 xmalloc(JNIEnv *env, size_t size)
135 135 {
136 136 void *p = malloc(size);
137 137 if (p == NULL)
138 138 JNU_ThrowOutOfMemoryError(env, NULL);
139 139 return p;
140 140 }
141 141
142 142 #define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
143 143
144 144 /**
↓ open down ↓ |
144 lines elided |
↑ open up ↑ |
145 145 * If PATH is not defined, the OS provides some default value.
146 146 * Unfortunately, there's no portable way to get this value.
147 147 * Fortunately, it's only needed if the child has PATH while we do not.
148 148 */
149 149 static const char*
150 150 defaultPath(void)
151 151 {
152 152 #ifdef __solaris__
153 153 /* These really are the Solaris defaults! */
154 154 return (geteuid() == 0 || getuid() == 0) ?
155 - "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
156 - "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:";
155 + "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
156 + "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:";
157 157 #else
158 158 return ":/bin:/usr/bin"; /* glibc */
159 159 #endif
160 160 }
161 161
162 162 static const char*
163 163 effectivePath(void)
164 164 {
165 165 const char *s = getenv("PATH");
166 166 return (s != NULL) ? s : defaultPath();
167 167 }
168 168
169 169 static int
170 170 countOccurrences(const char *s, char c)
171 171 {
172 172 int count;
173 173 for (count = 0; *s != '\0'; s++)
174 174 count += (*s == c);
175 175 return count;
176 176 }
177 177
178 178 static const char * const *
179 179 effectivePathv(JNIEnv *env)
180 180 {
181 181 char *p;
182 182 int i;
183 183 const char *path = effectivePath();
184 184 int count = countOccurrences(path, ':') + 1;
185 185 size_t pathvsize = sizeof(const char *) * (count+1);
186 186 size_t pathsize = strlen(path) + 1;
187 187 const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize);
188 188
189 189 if (pathv == NULL)
190 190 return NULL;
191 191 p = (char *) pathv + pathvsize;
192 192 memcpy(p, path, pathsize);
193 193 /* split PATH by replacing ':' with NULs; empty components => "." */
194 194 for (i = 0; i < count; i++) {
195 195 char *q = p + strcspn(p, ":");
196 196 pathv[i] = (p == q) ? "." : p;
197 197 *q = '\0';
198 198 p = q + 1;
199 199 }
200 200 pathv[count] = NULL;
201 201 return pathv;
202 202 }
203 203
204 204 JNIEXPORT void JNICALL
205 205 Java_java_lang_ProcessImpl_init(JNIEnv *env, jclass clazz)
206 206 {
207 207 parentPathv = effectivePathv(env);
208 208 CHECK_NULL(parentPathv);
209 209 setSIGCHLDHandler(env);
210 210 }
211 211
212 212
213 213 #ifndef WIFEXITED
214 214 #define WIFEXITED(status) (((status)&0xFF) == 0)
215 215 #endif
216 216
217 217 #ifndef WEXITSTATUS
218 218 #define WEXITSTATUS(status) (((status)>>8)&0xFF)
219 219 #endif
220 220
221 221 #ifndef WIFSIGNALED
222 222 #define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0)
223 223 #endif
224 224
225 225 #ifndef WTERMSIG
226 226 #define WTERMSIG(status) ((status)&0x7F)
227 227 #endif
228 228
229 229 static const char *
230 230 getBytes(JNIEnv *env, jbyteArray arr)
231 231 {
232 232 return arr == NULL ? NULL :
233 233 (const char*) (*env)->GetByteArrayElements(env, arr, NULL);
234 234 }
235 235
236 236 static void
237 237 releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr)
238 238 {
239 239 if (parr != NULL)
240 240 (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT);
241 241 }
242 242
243 243 #define IOE_FORMAT "error=%d, %s"
244 244
245 245 static void
246 246 throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
247 247 {
248 248 const char *detail = defaultDetail;
249 249 char *errmsg;
250 250 size_t fmtsize;
251 251 char tmpbuf[1024];
252 252 jstring s;
253 253
254 254 if (errnum != 0) {
255 255 int ret = getErrorString(errnum, tmpbuf, sizeof(tmpbuf));
256 256 if (ret != EINVAL)
257 257 detail = tmpbuf;
258 258 }
259 259 /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
260 260 fmtsize = sizeof(IOE_FORMAT) + strlen(detail) + 3 * sizeof(errnum);
261 261 errmsg = NEW(char, fmtsize);
262 262 if (errmsg == NULL)
263 263 return;
264 264
265 265 snprintf(errmsg, fmtsize, IOE_FORMAT, errnum, detail);
266 266 s = JNU_NewStringPlatform(env, errmsg);
267 267 if (s != NULL) {
268 268 jobject x = JNU_NewObjectByName(env, "java/io/IOException",
269 269 "(Ljava/lang/String;)V", s);
270 270 if (x != NULL)
271 271 (*env)->Throw(env, x);
272 272 }
273 273 free(errmsg);
274 274 }
275 275
276 276 #ifdef DEBUG_PROCESS
277 277 /* Debugging process code is difficult; where to write debug output? */
278 278 static void
279 279 debugPrint(char *format, ...)
280 280 {
281 281 FILE *tty = fopen("/dev/tty", "w");
282 282 va_list ap;
283 283 va_start(ap, format);
284 284 vfprintf(tty, format, ap);
285 285 va_end(ap);
286 286 fclose(tty);
287 287 }
288 288 #endif /* DEBUG_PROCESS */
289 289
290 290 static void
291 291 copyPipe(int from[2], int to[2])
292 292 {
293 293 to[0] = from[0];
294 294 to[1] = from[1];
295 295 }
296 296
297 297 /* arg is an array of pointers to 0 terminated strings. array is terminated
298 298 * by a null element.
299 299 *
300 300 * *nelems and *nbytes receive the number of elements of array (incl 0)
301 301 * and total number of bytes (incl. 0)
302 302 * Note. An empty array will have one null element
303 303 * But if arg is null, then *nelems set to 0, and *nbytes to 0
304 304 */
305 305 static void arraysize(const char * const *arg, int *nelems, int *nbytes)
306 306 {
307 307 int i, bytes, count;
308 308 const char * const *a = arg;
309 309 char *p;
310 310 int *q;
311 311 if (arg == 0) {
312 312 *nelems = 0;
313 313 *nbytes = 0;
314 314 return;
315 315 }
316 316 /* count the array elements and number of bytes */
317 317 for (count=0, bytes=0; *a != 0; count++, a++) {
318 318 bytes += strlen(*a)+1;
319 319 }
320 320 *nbytes = bytes;
321 321 *nelems = count+1;
322 322 }
323 323
324 324 /* copy the strings from arg[] into buf, starting at given offset
325 325 * return new offset to next free byte
326 326 */
327 327 static int copystrings(char *buf, int offset, const char * const *arg) {
328 328 char *p;
329 329 const char * const *a;
330 330 int count=0;
331 331
332 332 if (arg == 0) {
333 333 return offset;
334 334 }
335 335 for (p=buf+offset, a=arg; *a != 0; a++) {
336 336 int len = strlen(*a) +1;
337 337 memcpy(p, *a, len);
338 338 p += len;
339 339 count += len;
340 340 }
341 341 return offset+count;
342 342 }
343 343
344 344 /**
345 345 * We are unusually paranoid; use of vfork is
346 346 * especially likely to tickle gcc/glibc bugs.
347 347 */
348 348 #ifdef __attribute_noinline__ /* See: sys/cdefs.h */
349 349 __attribute_noinline__
350 350 #endif
351 351
352 352 static pid_t
353 353 vforkChild(ChildStuff *c) {
354 354 volatile pid_t resultPid;
355 355
356 356 /*
357 357 * We separate the call to vfork into a separate function to make
358 358 * very sure to keep stack of child from corrupting stack of parent,
359 359 * as suggested by the scary gcc warning:
360 360 * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
361 361 */
362 362 resultPid = vfork();
363 363
364 364 if (resultPid == 0) {
365 365 childProcess(c);
366 366 }
367 367 assert(resultPid != 0); /* childProcess never returns */
368 368 return resultPid;
369 369 }
370 370
371 371 static pid_t
372 372 forkChild(ChildStuff *c) {
373 373 pid_t resultPid;
374 374
375 375 /*
376 376 * From Solaris fork(2): In Solaris 10, a call to fork() is
377 377 * identical to a call to fork1(); only the calling thread is
378 378 * replicated in the child process. This is the POSIX-specified
379 379 * behavior for fork().
380 380 */
381 381 resultPid = fork();
382 382
383 383 if (resultPid == 0) {
384 384 childProcess(c);
385 385 }
386 386 assert(resultPid != 0); /* childProcess never returns */
387 387 return resultPid;
388 388 }
389 389
390 390 #if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
391 391 static pid_t
392 392 spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
393 393 pid_t resultPid;
394 394 jboolean isCopy;
395 395 int i, offset, rval, bufsize, magic;
396 396 char *buf, buf1[16];
397 397 char *hlpargs[2];
398 398 SpawnInfo sp;
399 399
400 400 /* need to tell helper which fd is for receiving the childstuff
401 401 * and which fd to send response back on
402 402 */
403 403 snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1]);
404 404 /* put the fd string as argument to the helper cmd */
405 405 hlpargs[0] = buf1;
406 406 hlpargs[1] = 0;
407 407
408 408 /* Following items are sent down the pipe to the helper
409 409 * after it is spawned.
410 410 * All strings are null terminated. All arrays of strings
411 411 * have an empty string for termination.
412 412 * - the ChildStuff struct
413 413 * - the SpawnInfo struct
414 414 * - the argv strings array
415 415 * - the envv strings array
416 416 * - the home directory string
417 417 * - the parentPath string
418 418 * - the parentPathv array
419 419 */
420 420 /* First calculate the sizes */
421 421 arraysize(c->argv, &sp.nargv, &sp.argvBytes);
422 422 bufsize = sp.argvBytes;
423 423 arraysize(c->envv, &sp.nenvv, &sp.envvBytes);
424 424 bufsize += sp.envvBytes;
425 425 sp.dirlen = c->pdir == 0 ? 0 : strlen(c->pdir)+1;
426 426 bufsize += sp.dirlen;
427 427 arraysize(parentPathv, &sp.nparentPathv, &sp.parentPathvBytes);
428 428 bufsize += sp.parentPathvBytes;
429 429 /* We need to clear FD_CLOEXEC if set in the fds[].
430 430 * Files are created FD_CLOEXEC in Java.
431 431 * Otherwise, they will be closed when the target gets exec'd */
432 432 for (i=0; i<3; i++) {
433 433 if (c->fds[i] != -1) {
434 434 int flags = fcntl(c->fds[i], F_GETFD);
435 435 if (flags & FD_CLOEXEC) {
436 436 fcntl(c->fds[i], F_SETFD, flags & (~1));
437 437 }
438 438 }
439 439 }
440 440
441 441 rval = posix_spawn(&resultPid, helperpath, 0, 0, (char * const *) hlpargs, environ);
442 442
443 443 if (rval != 0) {
444 444 return -1;
445 445 }
446 446
447 447 /* now the lengths are known, copy the data */
448 448 buf = NEW(char, bufsize);
449 449 if (buf == 0) {
450 450 return -1;
451 451 }
452 452 offset = copystrings(buf, 0, &c->argv[0]);
453 453 offset = copystrings(buf, offset, &c->envv[0]);
454 454 memcpy(buf+offset, c->pdir, sp.dirlen);
455 455 offset += sp.dirlen;
456 456 offset = copystrings(buf, offset, parentPathv);
457 457 assert(offset == bufsize);
458 458
459 459 magic = magicNumber();
460 460
461 461 /* write the two structs and the data buffer */
462 462 write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first
463 463 write(c->childenv[1], (char *)c, sizeof(*c));
464 464 write(c->childenv[1], (char *)&sp, sizeof(sp));
465 465 write(c->childenv[1], buf, bufsize);
466 466 free(buf);
467 467
468 468 /* In this mode an external main() in invoked which calls back into
469 469 * childProcess() in this file, rather than directly
470 470 * via the statement below */
471 471 return resultPid;
472 472 }
473 473 #endif
474 474
475 475 /*
476 476 * Start a child process running function childProcess.
477 477 * This function only returns in the parent.
478 478 */
479 479 static pid_t
480 480 startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
481 481 switch (c->mode) {
482 482 case MODE_VFORK:
483 483 return vforkChild(c);
484 484 case MODE_FORK:
485 485 return forkChild(c);
486 486 #if defined(__solaris__) || defined(_ALLBSD_SOURCE) || defined(_AIX)
487 487 case MODE_POSIX_SPAWN:
488 488 return spawnChild(env, process, c, helperpath);
489 489 #endif
490 490 default:
491 491 return -1;
492 492 }
493 493 }
494 494
495 495 JNIEXPORT jint JNICALL
496 496 Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env,
497 497 jobject process,
498 498 jint mode,
499 499 jbyteArray helperpath,
500 500 jbyteArray prog,
501 501 jbyteArray argBlock, jint argc,
502 502 jbyteArray envBlock, jint envc,
503 503 jbyteArray dir,
504 504 jintArray std_fds,
505 505 jboolean redirectErrorStream)
506 506 {
507 507 int errnum;
508 508 int resultPid = -1;
509 509 int in[2], out[2], err[2], fail[2], childenv[2];
510 510 jint *fds = NULL;
511 511 const char *phelperpath = NULL;
512 512 const char *pprog = NULL;
513 513 const char *pargBlock = NULL;
514 514 const char *penvBlock = NULL;
515 515 ChildStuff *c;
516 516
517 517 in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1;
518 518 childenv[0] = childenv[1] = -1;
519 519
520 520 if ((c = NEW(ChildStuff, 1)) == NULL) return -1;
521 521 c->argv = NULL;
522 522 c->envv = NULL;
523 523 c->pdir = NULL;
524 524
525 525 /* Convert prog + argBlock into a char ** argv.
526 526 * Add one word room for expansion of argv for use by
527 527 * execve_as_traditional_shell_script.
528 528 * This word is also used when using posix_spawn mode
529 529 */
530 530 assert(prog != NULL && argBlock != NULL);
531 531 if ((phelperpath = getBytes(env, helperpath)) == NULL) goto Catch;
532 532 if ((pprog = getBytes(env, prog)) == NULL) goto Catch;
533 533 if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch;
534 534 if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch;
535 535 c->argv[0] = pprog;
536 536 c->argc = argc + 2;
537 537 initVectorFromBlock(c->argv+1, pargBlock, argc);
538 538
539 539 if (envBlock != NULL) {
540 540 /* Convert envBlock into a char ** envv */
541 541 if ((penvBlock = getBytes(env, envBlock)) == NULL) goto Catch;
542 542 if ((c->envv = NEW(const char *, envc + 1)) == NULL) goto Catch;
543 543 initVectorFromBlock(c->envv, penvBlock, envc);
544 544 }
545 545
546 546 if (dir != NULL) {
547 547 if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch;
548 548 }
549 549
550 550 assert(std_fds != NULL);
551 551 fds = (*env)->GetIntArrayElements(env, std_fds, NULL);
552 552 if (fds == NULL) goto Catch;
553 553
554 554 if ((fds[0] == -1 && pipe(in) < 0) ||
555 555 (fds[1] == -1 && pipe(out) < 0) ||
556 556 (fds[2] == -1 && pipe(err) < 0) ||
557 557 (pipe(childenv) < 0) ||
558 558 (pipe(fail) < 0)) {
559 559 throwIOException(env, errno, "Bad file descriptor");
560 560 goto Catch;
561 561 }
562 562 c->fds[0] = fds[0];
563 563 c->fds[1] = fds[1];
564 564 c->fds[2] = fds[2];
565 565
566 566 copyPipe(in, c->in);
567 567 copyPipe(out, c->out);
568 568 copyPipe(err, c->err);
569 569 copyPipe(fail, c->fail);
570 570 copyPipe(childenv, c->childenv);
571 571
572 572 c->redirectErrorStream = redirectErrorStream;
573 573 c->mode = mode;
574 574
575 575 resultPid = startChild(env, process, c, phelperpath);
576 576 assert(resultPid != 0);
577 577
578 578 if (resultPid < 0) {
579 579 switch (c->mode) {
580 580 case MODE_VFORK:
581 581 throwIOException(env, errno, "vfork failed");
582 582 break;
583 583 case MODE_FORK:
584 584 throwIOException(env, errno, "fork failed");
585 585 break;
586 586 case MODE_POSIX_SPAWN:
587 587 throwIOException(env, errno, "posix_spawn failed");
588 588 break;
589 589 }
590 590 goto Catch;
591 591 }
592 592 close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec (childproc.c) */
593 593
594 594 switch (readFully(fail[0], &errnum, sizeof(errnum))) {
595 595 case 0: break; /* Exec succeeded */
596 596 case sizeof(errnum):
597 597 waitpid(resultPid, NULL, 0);
598 598 throwIOException(env, errnum, "Exec failed");
599 599 goto Catch;
600 600 default:
601 601 throwIOException(env, errno, "Read failed");
602 602 goto Catch;
603 603 }
604 604
605 605 fds[0] = (in [1] != -1) ? in [1] : -1;
606 606 fds[1] = (out[0] != -1) ? out[0] : -1;
607 607 fds[2] = (err[0] != -1) ? err[0] : -1;
608 608
609 609 Finally:
610 610 /* Always clean up the child's side of the pipes */
611 611 closeSafely(in [0]);
612 612 closeSafely(out[1]);
613 613 closeSafely(err[1]);
614 614
615 615 /* Always clean up fail and childEnv descriptors */
616 616 closeSafely(fail[0]);
617 617 closeSafely(fail[1]);
618 618 closeSafely(childenv[0]);
619 619 closeSafely(childenv[1]);
620 620
621 621 releaseBytes(env, helperpath, phelperpath);
622 622 releaseBytes(env, prog, pprog);
623 623 releaseBytes(env, argBlock, pargBlock);
624 624 releaseBytes(env, envBlock, penvBlock);
625 625 releaseBytes(env, dir, c->pdir);
626 626
627 627 free(c->argv);
628 628 free(c->envv);
629 629 free(c);
630 630
631 631 if (fds != NULL)
632 632 (*env)->ReleaseIntArrayElements(env, std_fds, fds, 0);
633 633
634 634 return resultPid;
635 635
636 636 Catch:
637 637 /* Clean up the parent's side of the pipes in case of failure only */
638 638 closeSafely(in [1]); in[1] = -1;
639 639 closeSafely(out[0]); out[0] = -1;
640 640 closeSafely(err[0]); err[0] = -1;
641 641 goto Finally;
642 642 }
643 643
↓ open down ↓ |
477 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX