1/*
2 * Copyright (c) 1995, 2018, 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
26#undef _LARGEFILE64_SOURCE
27#define _LARGEFILE64_SOURCE 1
28
29#include "jni.h"
30#include "jvm.h"
31#include "jvm_md.h"
32#include "jni_util.h"
33#include "io_util.h"
34
35/*
36 * Platform-specific support for java.lang.Process
37 */
38#include <assert.h>
39#include <stddef.h>
40#include <stdlib.h>
41#include <sys/types.h>
42#include <ctype.h>
43#include <sys/wait.h>
44#include <signal.h>
45#include <string.h>
46
47#include <spawn.h>
48
49#include "childproc.h"
50
51/*
52 *
53 * When starting a child on Unix, we need to do three things:
54 * - fork off
55 * - in the child process, do some pre-exec work: duping/closing file
56 * descriptors to set up stdio-redirection, setting environment variables,
57 * changing paths...
58 * - then exec(2) the target binary
59 *
60 * There are three ways to fork off:
61 *
62 * A) fork(2). Portable and safe (no side effects) but may fail with ENOMEM on
63 * all Unices when invoked from a VM with a high memory footprint. On Unices
64 * with strict no-overcommit policy this problem is most visible.
65 *
66 * This is because forking the VM will first create a child process with
67 * theoretically the same memory footprint as the parent - even if you plan
68 * to follow up with exec'ing a tiny binary. In reality techniques like
69 * copy-on-write etc mitigate the problem somewhat but we still run the risk
70 * of hitting system limits.
71 *
72 * For a Linux centric description of this problem, see the documentation on
73 * /proc/sys/vm/overcommit_memory in Linux proc(5).
74 *
75 * B) vfork(2): Portable and fast but very unsafe. It bypasses the memory
76 * problems related to fork(2) by starting the child in the memory image of
77 * the parent. Things that can go wrong include:
78 * - Programming errors in the child process before the exec(2) call may
79 * trash memory in the parent process, most commonly the stack of the
80 * thread invoking vfork.
81 * - Signals received by the child before the exec(2) call may be at best
82 * misdirected to the parent, at worst immediately kill child and parent.
83 *
84 * This is mitigated by very strict rules about what one is allowed to do in
85 * the child process between vfork(2) and exec(2), which is basically nothing.
86 * However, we always broke this rule by doing the pre-exec work between
87 * vfork(2) and exec(2).
88 *
89 * Also note that vfork(2) has been deprecated by the OpenGroup, presumably
90 * because of its many dangers.
91 *
92 * C) clone(2): This is a Linux specific call which gives the caller fine
93 * grained control about how exactly the process fork is executed. It is
94 * powerful, but Linux-specific.
95 *
96 * Aside from these three possibilities there is a forth option: posix_spawn(3).
97 * Where fork/vfork/clone all fork off the process and leave pre-exec work and
98 * calling exec(2) to the user, posix_spawn(3) offers the user fork+exec-like
99 * functionality in one package, similar to CreateProcess() on Windows.
100 *
101 * It is not a system call in itself, but usually a wrapper implemented within
102 * the libc in terms of one of (fork|vfork|clone)+exec - so whether or not it
103 * has advantages over calling the naked (fork|vfork|clone) functions depends
104 * on how posix_spawn(3) is implemented.
105 *
106 * Note that when using posix_spawn(3), we exec twice: first a tiny binary called
107 * the jspawnhelper, then in the jspawnhelper we do the pre-exec work and exec a
108 * second time, this time the target binary (similar to the "exec-twice-technique"
109 * described in http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-September/055333.html).
110 *
111 * This is a JDK-specific implementation detail which just happens to be
112 * implemented for jdk.lang.Process.launchMechanism=POSIX_SPAWN.
113 *
114 * --- Linux-specific ---
115 *
116 * How does glibc implement posix_spawn?
117 * (see: sysdeps/posix/spawni.c for glibc < 2.24,
118 * sysdeps/unix/sysv/linux/spawni.c for glibc >= 2.24):
119 *
120 * 1) Before glibc 2.4 (released 2006), posix_spawn(3) used just fork(2)/exec(2).
121 * This would be bad for the JDK since we would risk the known memory issues with
122 * fork(2). But since this only affects glibc variants which have long been
123 * phased out by modern distributions, this is irrelevant.
124 *
125 * 2) Between glibc 2.4 and glibc 2.23, posix_spawn uses either fork(2) or
126 * vfork(2) depending on how exactly the user called posix_spawn(3):
127 *
128 * <quote>
129 * The child process is created using vfork(2) instead of fork(2) when
130 * either of the following is true:
131 *
132 * * the spawn-flags element of the attributes object pointed to by
133 * attrp contains the GNU-specific flag POSIX_SPAWN_USEVFORK; or
134 *
135 * * file_actions is NULL and the spawn-flags element of the attributes
136 * object pointed to by attrp does not contain
137 * POSIX_SPAWN_SETSIGMASK, POSIX_SPAWN_SETSIGDEF,
138 * POSIX_SPAWN_SETSCHEDPARAM, POSIX_SPAWN_SETSCHEDULER,
139 * POSIX_SPAWN_SETPGROUP, or POSIX_SPAWN_RESETIDS.
140 * </quote>
141 *
142 * Due to the way the JDK calls posix_spawn(3), it would therefore call vfork(2).
143 * So we would avoid the fork(2) memory problems. However, there still remains the
144 * risk associated with vfork(2). But it is smaller than were we to call vfork(2)
145 * directly since we use the jspawnhelper, moving all pre-exec work off to after
146 * the first exec, thereby reducing the vulnerable time window.
147 *
148 * 3) Since glibc >= 2.24, glibc uses clone+exec:
149 *
150 * new_pid = CLONE (__spawni_child, STACK (stack, stack_size), stack_size,
151 * CLONE_VM | CLONE_VFORK | SIGCHLD, &args);
152 *
153 * This is even better than (2):
154 *
155 * CLONE_VM means we run in the parent's memory image, as with (2)
156 * CLONE_VFORK means parent waits until we exec, as with (2)
157 *
158 * However, error possibilities are further reduced since:
159 * - posix_spawn(3) passes a separate stack for the child to run on, eliminating
160 * the danger of trashing the forking thread's stack in the parent process.
161 * - posix_spawn(3) takes care to temporarily block all incoming signals to the
162 * child process until the first exec(2) has been called,
163 *
164 * TL;DR
165 * Calling posix_spawn(3) for glibc
166 * (2) < 2.24 is not perfect but still better than using plain vfork(2), since
167 * the chance of an error happening is greatly reduced
168 * (3) >= 2.24 is the best option - portable, fast and as safe as possible.
169 *
170 * ---
171 *
172 * How does muslc implement posix_spawn?
173 *
174 * They always did use the clone (.. CLONE_VM | CLONE_VFORK ...)
175 * technique. So we are safe to use posix_spawn() here regardless of muslc
176 * version.
177 *
178 * </Linux-specific>
179 *
180 *
181 * Based on the above analysis, we are currently defaulting to posix_spawn()
182 * on all Unices including Linux.
183 */
184
185static void
186setSIGCHLDHandler(JNIEnv *env)
187{
188 /* There is a subtle difference between having the signal handler
189 * for SIGCHLD be SIG_DFL and SIG_IGN. We cannot obtain process
190 * termination information for child processes if the signal
191 * handler is SIG_IGN. It must be SIG_DFL.
192 *
193 * We used to set the SIGCHLD handler only on Linux, but it's
194 * safest to set it unconditionally.
195 *
196 * Consider what happens if java's parent process sets the SIGCHLD
197 * handler to SIG_IGN. Normally signal handlers are inherited by
198 * children, but SIGCHLD is a controversial case. Solaris appears
199 * to always reset it to SIG_DFL, but this behavior may be
200 * non-standard-compliant, and we shouldn't rely on it.
201 *
202 * References:
203 * http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html
204 * http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html
205 */
206 struct sigaction sa;
207 sa.sa_handler = SIG_DFL;
208 sigemptyset(&sa.sa_mask);
209 sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
210 if (sigaction(SIGCHLD, &sa, NULL) < 0)
211 JNU_ThrowInternalError(env, "Can't set SIGCHLD handler");
212}
213
214static void*
215xmalloc(JNIEnv *env, size_t size)
216{
217 void *p = malloc(size);
218 if (p == NULL)
219 JNU_ThrowOutOfMemoryError(env, NULL);
220 return p;
221}
222
223#define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
224
225/**
226 * If PATH is not defined, the OS provides some default value.
227 * Unfortunately, there's no portable way to get this value.
228 * Fortunately, it's only needed if the child has PATH while we do not.
229 */
230static const char*
231defaultPath(void)
232{
233#ifdef __solaris__
234 /* These really are the Solaris defaults! */
235 return (geteuid() == 0 || getuid() == 0) ?
236 "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
237 "/usr/xpg4/bin:/usr/bin:/opt/SUNWspro/bin:";
238#else
239 return ":/bin:/usr/bin"; /* glibc */
240#endif
241}
242
243static const char*
244effectivePath(void)
245{
246 const char *s = getenv("PATH");
247 return (s != NULL) ? s : defaultPath();
248}
249
250static int
251countOccurrences(const char *s, char c)
252{
253 int count;
254 for (count = 0; *s != '\0'; s++)
255 count += (*s == c);
256 return count;
257}
258
259static const char * const *
260effectivePathv(JNIEnv *env)
261{
262 char *p;
263 int i;
264 const char *path = effectivePath();
265 int count = countOccurrences(path, ':') + 1;
266 size_t pathvsize = sizeof(const char *) * (count+1);
267 size_t pathsize = strlen(path) + 1;
268 const char **pathv = (const char **) xmalloc(env, pathvsize + pathsize);
269
270 if (pathv == NULL)
271 return NULL;
272 p = (char *) pathv + pathvsize;
273 memcpy(p, path, pathsize);
274 /* split PATH by replacing ':' with NULs; empty components => "." */
275 for (i = 0; i < count; i++) {
276 char *q = p + strcspn(p, ":");
277 pathv[i] = (p == q) ? "." : p;
278 *q = '\0';
279 p = q + 1;
280 }
281 pathv[count] = NULL;
282 return pathv;
283}
284
285JNIEXPORT void JNICALL
286Java_java_lang_ProcessImpl_init(JNIEnv *env, jclass clazz)
287{
288 parentPathv = effectivePathv(env);
289 CHECK_NULL(parentPathv);
290 setSIGCHLDHandler(env);
291}
292
293
294#ifndef WIFEXITED
295#define WIFEXITED(status) (((status)&0xFF) == 0)
296#endif
297
298#ifndef WEXITSTATUS
299#define WEXITSTATUS(status) (((status)>>8)&0xFF)
300#endif
301
302#ifndef WIFSIGNALED
303#define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0)
304#endif
305
306#ifndef WTERMSIG
307#define WTERMSIG(status) ((status)&0x7F)
308#endif
309
310static const char *
311getBytes(JNIEnv *env, jbyteArray arr)
312{
313 return arr == NULL ? NULL :
314 (const char*) (*env)->GetByteArrayElements(env, arr, NULL);
315}
316
317static void
318releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr)
319{
320 if (parr != NULL)
321 (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT);
322}
323
324#define IOE_FORMAT "error=%d, %s"
325
326static void
327throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
328{
329 const char *detail = defaultDetail;
330 char *errmsg;
331 size_t fmtsize;
332 char tmpbuf[1024];
333 jstring s;
334
335 if (errnum != 0) {
336 int ret = getErrorString(errnum, tmpbuf, sizeof(tmpbuf));
337 if (ret != EINVAL)
338 detail = tmpbuf;
339 }
340 /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
341 fmtsize = sizeof(IOE_FORMAT) + strlen(detail) + 3 * sizeof(errnum);
342 errmsg = NEW(char, fmtsize);
343 if (errmsg == NULL)
344 return;
345
346 snprintf(errmsg, fmtsize, IOE_FORMAT, errnum, detail);
347 s = JNU_NewStringPlatform(env, errmsg);
348 if (s != NULL) {
349 jobject x = JNU_NewObjectByName(env, "java/io/IOException",
350 "(Ljava/lang/String;)V", s);
351 if (x != NULL)
352 (*env)->Throw(env, x);
353 }
354 free(errmsg);
355}
356
357#ifdef DEBUG_PROCESS
358/* Debugging process code is difficult; where to write debug output? */
359static void
360debugPrint(char *format, ...)
361{
362 FILE *tty = fopen("/dev/tty", "w");
363 va_list ap;
364 va_start(ap, format);
365 vfprintf(tty, format, ap);
366 va_end(ap);
367 fclose(tty);
368}
369#endif /* DEBUG_PROCESS */
370
371static void
372copyPipe(int from[2], int to[2])
373{
374 to[0] = from[0];
375 to[1] = from[1];
376}
377
378/* arg is an array of pointers to 0 terminated strings. array is terminated
379 * by a null element.
380 *
381 * *nelems and *nbytes receive the number of elements of array (incl 0)
382 * and total number of bytes (incl. 0)
383 * Note. An empty array will have one null element
384 * But if arg is null, then *nelems set to 0, and *nbytes to 0
385 */
386static void arraysize(const char * const *arg, int *nelems, int *nbytes)
387{
388 int i, bytes, count;
389 const char * const *a = arg;
390 char *p;
391 int *q;
392 if (arg == 0) {
393 *nelems = 0;
394 *nbytes = 0;
395 return;
396 }
397 /* count the array elements and number of bytes */
398 for (count=0, bytes=0; *a != 0; count++, a++) {
399 bytes += strlen(*a)+1;
400 }
401 *nbytes = bytes;
402 *nelems = count+1;
403}
404
405/* copy the strings from arg[] into buf, starting at given offset
406 * return new offset to next free byte
407 */
408static int copystrings(char *buf, int offset, const char * const *arg) {
409 char *p;
410 const char * const *a;
411 int count=0;
412
413 if (arg == 0) {
414 return offset;
415 }
416 for (p=buf+offset, a=arg; *a != 0; a++) {
417 int len = strlen(*a) +1;
418 memcpy(p, *a, len);
419 p += len;
420 count += len;
421 }
422 return offset+count;
423}
424
425/**
426 * We are unusually paranoid; use of vfork is
427 * especially likely to tickle gcc/glibc bugs.
428 */
429#ifdef __attribute_noinline__ /* See: sys/cdefs.h */
430__attribute_noinline__
431#endif
432
433/* vfork(2) is deprecated on Solaris */
434#ifndef __solaris__
435static pid_t
436vforkChild(ChildStuff *c) {
437 volatile pid_t resultPid;
438
439 /*
440 * We separate the call to vfork into a separate function to make
441 * very sure to keep stack of child from corrupting stack of parent,
442 * as suggested by the scary gcc warning:
443 * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
444 */
445 resultPid = vfork();
446
447 if (resultPid == 0) {
448 childProcess(c);
449 }
450 assert(resultPid != 0); /* childProcess never returns */
451 return resultPid;
452}
453#endif
454
455static pid_t
456forkChild(ChildStuff *c) {
457 pid_t resultPid;
458
459 /*
460 * From Solaris fork(2): In Solaris 10, a call to fork() is
461 * identical to a call to fork1(); only the calling thread is
462 * replicated in the child process. This is the POSIX-specified
463 * behavior for fork().
464 */
465 resultPid = fork();
466
467 if (resultPid == 0) {
468 childProcess(c);
469 }
470 assert(resultPid != 0); /* childProcess never returns */
471 return resultPid;
472}
473
474static pid_t
475spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
476 pid_t resultPid;
477 jboolean isCopy;
478 int i, offset, rval, bufsize, magic;
479 char *buf, buf1[16];
480 char *hlpargs[2];
481 SpawnInfo sp;
482
483 /* need to tell helper which fd is for receiving the childstuff
484 * and which fd to send response back on
485 */
486 snprintf(buf1, sizeof(buf1), "%d:%d", c->childenv[0], c->fail[1]);
487 /* put the fd string as argument to the helper cmd */
488 hlpargs[0] = buf1;
489 hlpargs[1] = 0;
490
491 /* Following items are sent down the pipe to the helper
492 * after it is spawned.
493 * All strings are null terminated. All arrays of strings
494 * have an empty string for termination.
495 * - the ChildStuff struct
496 * - the SpawnInfo struct
497 * - the argv strings array
498 * - the envv strings array
499 * - the home directory string
500 * - the parentPath string
501 * - the parentPathv array
502 */
503 /* First calculate the sizes */
504 arraysize(c->argv, &sp.nargv, &sp.argvBytes);
505 bufsize = sp.argvBytes;
506 arraysize(c->envv, &sp.nenvv, &sp.envvBytes);
507 bufsize += sp.envvBytes;
508 sp.dirlen = c->pdir == 0 ? 0 : strlen(c->pdir)+1;
509 bufsize += sp.dirlen;
510 arraysize(parentPathv, &sp.nparentPathv, &sp.parentPathvBytes);
511 bufsize += sp.parentPathvBytes;
512 /* We need to clear FD_CLOEXEC if set in the fds[].
513 * Files are created FD_CLOEXEC in Java.
514 * Otherwise, they will be closed when the target gets exec'd */
515 for (i=0; i<3; i++) {
516 if (c->fds[i] != -1) {
517 int flags = fcntl(c->fds[i], F_GETFD);
518 if (flags & FD_CLOEXEC) {
519 fcntl(c->fds[i], F_SETFD, flags & (~1));
520 }
521 }
522 }
523
524 rval = posix_spawn(&resultPid, helperpath, 0, 0, (char * const *) hlpargs, environ);
525
526 if (rval != 0) {
527 return -1;
528 }
529
530 /* now the lengths are known, copy the data */
531 buf = NEW(char, bufsize);
532 if (buf == 0) {
533 return -1;
534 }
535 offset = copystrings(buf, 0, &c->argv[0]);
536 offset = copystrings(buf, offset, &c->envv[0]);
537 memcpy(buf+offset, c->pdir, sp.dirlen);
538 offset += sp.dirlen;
539 offset = copystrings(buf, offset, parentPathv);
540 assert(offset == bufsize);
541
542 magic = magicNumber();
543
544 /* write the two structs and the data buffer */
545 write(c->childenv[1], (char *)&magic, sizeof(magic)); // magic number first
546 write(c->childenv[1], (char *)c, sizeof(*c));
547 write(c->childenv[1], (char *)&sp, sizeof(sp));
548 write(c->childenv[1], buf, bufsize);
549 free(buf);
550
551 /* In this mode an external main() in invoked which calls back into
552 * childProcess() in this file, rather than directly
553 * via the statement below */
554 return resultPid;
555}
556
557/*
558 * Start a child process running function childProcess.
559 * This function only returns in the parent.
560 */
561static pid_t
562startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath) {
563 switch (c->mode) {
564/* vfork(2) is deprecated on Solaris */
565#ifndef __solaris__
566 case MODE_VFORK:
567 return vforkChild(c);
568#endif
569 case MODE_FORK:
570 return forkChild(c);
571 case MODE_POSIX_SPAWN:
572 return spawnChild(env, process, c, helperpath);
573 default:
574 return -1;
575 }
576}
577
578JNIEXPORT jint JNICALL
579Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env,
580 jobject process,
581 jint mode,
582 jbyteArray helperpath,
583 jbyteArray prog,
584 jbyteArray argBlock, jint argc,
585 jbyteArray envBlock, jint envc,
586 jbyteArray dir,
587 jintArray std_fds,
588 jboolean redirectErrorStream)
589{
590 int errnum;
591 int resultPid = -1;
592 int in[2], out[2], err[2], fail[2], childenv[2];
593 jint *fds = NULL;
594 const char *phelperpath = NULL;
595 const char *pprog = NULL;
596 const char *pargBlock = NULL;
597 const char *penvBlock = NULL;
598 ChildStuff *c;
599
600 in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1;
601 childenv[0] = childenv[1] = -1;
602
603 if ((c = NEW(ChildStuff, 1)) == NULL) return -1;
604 c->argv = NULL;
605 c->envv = NULL;
606 c->pdir = NULL;
607
608 /* Convert prog + argBlock into a char ** argv.
609 * Add one word room for expansion of argv for use by
610 * execve_as_traditional_shell_script.
611 * This word is also used when using posix_spawn mode
612 */
613 assert(prog != NULL && argBlock != NULL);
614 if ((phelperpath = getBytes(env, helperpath)) == NULL) goto Catch;
615 if ((pprog = getBytes(env, prog)) == NULL) goto Catch;
616 if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch;
617 if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch;
618 c->argv[0] = pprog;
619 c->argc = argc + 2;
620 initVectorFromBlock(c->argv+1, pargBlock, argc);
621
622 if (envBlock != NULL) {
623 /* Convert envBlock into a char ** envv */
624 if ((penvBlock = getBytes(env, envBlock)) == NULL) goto Catch;
625 if ((c->envv = NEW(const char *, envc + 1)) == NULL) goto Catch;
626 initVectorFromBlock(c->envv, penvBlock, envc);
627 }
628
629 if (dir != NULL) {
630 if ((c->pdir = getBytes(env, dir)) == NULL) goto Catch;
631 }
632
633 assert(std_fds != NULL);
634 fds = (*env)->GetIntArrayElements(env, std_fds, NULL);
635 if (fds == NULL) goto Catch;
636
637 if ((fds[0] == -1 && pipe(in) < 0) ||
638 (fds[1] == -1 && pipe(out) < 0) ||
639 (fds[2] == -1 && pipe(err) < 0) ||
640 (pipe(childenv) < 0) ||
641 (pipe(fail) < 0)) {
642 throwIOException(env, errno, "Bad file descriptor");
643 goto Catch;
644 }
645 c->fds[0] = fds[0];
646 c->fds[1] = fds[1];
647 c->fds[2] = fds[2];
648
649 copyPipe(in, c->in);
650 copyPipe(out, c->out);
651 copyPipe(err, c->err);
652 copyPipe(fail, c->fail);
653 copyPipe(childenv, c->childenv);
654
655 c->redirectErrorStream = redirectErrorStream;
656 c->mode = mode;
657
658 /* In posix_spawn mode, require the child process to signal aliveness
659 * right after it comes up. This is because there are implementations of
660 * posix_spawn() which do not report failed exec()s back to the caller
661 * (e.g. glibc, see JDK-8223777). In those cases, the fork() will have
662 * worked and successfully started the child process, but the exec() will
663 * have failed. There is no way for us to distinguish this from a target
664 * binary just exiting right after start.
665 *
666 * Note that we could do this additional handshake in all modes but for
667 * prudence only do it when it is needed (in posix_spawn mode). */
668 c->sendAlivePing = (mode == MODE_POSIX_SPAWN) ? 1 : 0;
669
670 resultPid = startChild(env, process, c, phelperpath);
671 assert(resultPid != 0);
672
673 if (resultPid < 0) {
674 switch (c->mode) {
675 case MODE_VFORK:
676 throwIOException(env, errno, "vfork failed");
677 break;
678 case MODE_FORK:
679 throwIOException(env, errno, "fork failed");
680 break;
681 case MODE_POSIX_SPAWN:
682 throwIOException(env, errno, "posix_spawn failed");
683 break;
684 }
685 goto Catch;
686 }
687 close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec (childproc.c) */
688
689 /* If we expect the child to ping aliveness, wait for it. */
690 if (c->sendAlivePing) {
691 switch(readFully(fail[0], &errnum, sizeof(errnum))) {
692 case 0: /* First exec failed; */
693 waitpid(resultPid, NULL, 0);
694 throwIOException(env, 0, "Failed to exec spawn helper.");
695 goto Catch;
696 case sizeof(errnum):
697 assert(errnum == CHILD_IS_ALIVE);
698 if (errnum != CHILD_IS_ALIVE) {
699 /* Should never happen since the first thing the spawn
700 * helper should do is to send an alive ping to the parent,
701 * before doing any subsequent work. */
702 throwIOException(env, 0, "Bad code from spawn helper "
703 "(Failed to exec spawn helper.");
704 goto Catch;
705 }
706 break;
707 default:
708 throwIOException(env, errno, "Read failed");
709 goto Catch;
710 }
711 }
712
713 switch (readFully(fail[0], &errnum, sizeof(errnum))) {
714 case 0: break; /* Exec succeeded */
715 case sizeof(errnum):
716 waitpid(resultPid, NULL, 0);
717 throwIOException(env, errnum, "Exec failed");
718 goto Catch;
719 default:
720 throwIOException(env, errno, "Read failed");
721 goto Catch;
722 }
723
724 fds[0] = (in [1] != -1) ? in [1] : -1;
725 fds[1] = (out[0] != -1) ? out[0] : -1;
726 fds[2] = (err[0] != -1) ? err[0] : -1;
727
728 Finally:
729 /* Always clean up the child's side of the pipes */
730 closeSafely(in [0]);
731 closeSafely(out[1]);
732 closeSafely(err[1]);
733
734 /* Always clean up fail and childEnv descriptors */
735 closeSafely(fail[0]);
736 closeSafely(fail[1]);
737 closeSafely(childenv[0]);
738 closeSafely(childenv[1]);
739
740 releaseBytes(env, helperpath, phelperpath);
741 releaseBytes(env, prog, pprog);
742 releaseBytes(env, argBlock, pargBlock);
743 releaseBytes(env, envBlock, penvBlock);
744 releaseBytes(env, dir, c->pdir);
745
746 free(c->argv);
747 free(c->envv);
748 free(c);
749
750 if (fds != NULL)
751 (*env)->ReleaseIntArrayElements(env, std_fds, fds, 0);
752
753 return resultPid;
754
755 Catch:
756 /* Clean up the parent's side of the pipes in case of failure only */
757 closeSafely(in [1]); in[1] = -1;
758 closeSafely(out[0]); out[0] = -1;
759 closeSafely(err[0]); err[0] = -1;
760 goto Finally;
761}
762
763