src/solaris/native/java/lang/UNIXProcess_md.c
author ohair
Tue May 25 14:40:38 2010 -0700 (24 months ago)
changeset 354 ffa98eed5766
parent 161eb90e0cf5456
permissions -rw-r--r--
6943119: Rebrand source copyright notices
Reviewed-by: darcy, weijun
        1 /*
        2  * Copyright (c) 1995, 2006, 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 <wait.h>
       44 #include <signal.h>
       45 #include <string.h>
       46 #include <errno.h>
       47 #include <dirent.h>
       48 #include <unistd.h>
       49 #include <fcntl.h>
       50 #include <limits.h>
       51 
       52 #ifndef STDIN_FILENO
       53 #define STDIN_FILENO 0
       54 #endif
       55 
       56 #ifndef STDOUT_FILENO
       57 #define STDOUT_FILENO 1
       58 #endif
       59 
       60 #ifndef STDERR_FILENO
       61 #define STDERR_FILENO 2
       62 #endif
       63 
       64 #ifndef SA_NOCLDSTOP
       65 #define SA_NOCLDSTOP 0
       66 #endif
       67 
       68 #ifndef SA_RESTART
       69 #define SA_RESTART 0
       70 #endif
       71 
       72 #define FAIL_FILENO (STDERR_FILENO + 1)
       73 
       74 static void
       75 setSIGCHLDHandler(JNIEnv *env)
       76 {
       77     /* There is a subtle difference between having the signal handler
       78      * for SIGCHLD be SIG_DFL and SIG_IGN.  We cannot obtain process
       79      * termination information for child processes if the signal
       80      * handler is SIG_IGN.  It must be SIG_DFL.
       81      *
       82      * We used to set the SIGCHLD handler only on Linux, but it's
       83      * safest to set it unconditionally.
       84      *
       85      * Consider what happens if java's parent process sets the SIGCHLD
       86      * handler to SIG_IGN.  Normally signal handlers are inherited by
       87      * children, but SIGCHLD is a controversial case.  Solaris appears
       88      * to always reset it to SIG_DFL, but this behavior may be
       89      * non-standard-compliant, and we shouldn't rely on it.
       90      *
       91      * References:
       92      * http://www.opengroup.org/onlinepubs/7908799/xsh/exec.html
       93      * http://www.pasc.org/interps/unofficial/db/p1003.1/pasc-1003.1-132.html
       94      */
       95     struct sigaction sa;
       96     sa.sa_handler = SIG_DFL;
       97     sigemptyset(&sa.sa_mask);
       98     sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
       99     if (sigaction(SIGCHLD, &sa, NULL) < 0)
      100         JNU_ThrowInternalError(env, "Can't set SIGCHLD handler");
      101 }
      102 
      103 static void*
      104 xmalloc(JNIEnv *env, size_t size)
      105 {
      106     void *p = malloc(size);
      107     if (p == NULL)
      108         JNU_ThrowOutOfMemoryError(env, NULL);
      109     return p;
      110 }
      111 
      112 #define NEW(type, n) ((type *) xmalloc(env, (n) * sizeof(type)))
      113 
      114 /**
      115  * If PATH is not defined, the OS provides some default value.
      116  * Unfortunately, there's no portable way to get this value.
      117  * Fortunately, it's only needed if the child has PATH while we do not.
      118  */
      119 static const char*
      120 defaultPath(void)
      121 {
      122 #ifdef __solaris__
      123     /* These really are the Solaris defaults! */
      124     return (geteuid() == 0 || getuid() == 0) ?
      125         "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:/usr/sbin" :
      126         "/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin:";
      127 #else
      128     return ":/bin:/usr/bin";    /* glibc */
      129 #endif
      130 }
      131 
      132 static const char*
      133 effectivePath(void)
      134 {
      135     const char *s = getenv("PATH");
      136     return (s != NULL) ? s : defaultPath();
      137 }
      138 
      139 static int
      140 countOccurrences(const char *s, char c)
      141 {
      142     int count;
      143     for (count = 0; *s != '\0'; s++)
      144         count += (*s == c);
      145     return count;
      146 }
      147 
      148 static const char * const *
      149 splitPath(JNIEnv *env, const char *path)
      150 {
      151     const char *p, *q;
      152     char **pathv;
      153     int i;
      154     int count = countOccurrences(path, ':') + 1;
      155 
      156     pathv = NEW(char*, count+1);
      157     pathv[count] = NULL;
      158     for (p = path, i = 0; i < count; i++, p = q + 1) {
      159         for (q = p; (*q != ':') && (*q != '\0'); q++)
      160             ;
      161         if (q == p)             /* empty PATH component => "." */
      162             pathv[i] = "./";
      163         else {
      164             int addSlash = ((*(q - 1)) != '/');
      165             pathv[i] = NEW(char, q - p + addSlash + 1);
      166             memcpy(pathv[i], p, q - p);
      167             if (addSlash)
      168                 pathv[i][q - p] = '/';
      169             pathv[i][q - p + addSlash] = '\0';
      170         }
      171     }
      172     return (const char * const *) pathv;
      173 }
      174 
      175 /**
      176  * Cached value of JVM's effective PATH.
      177  * (We don't support putenv("PATH=...") in native code)
      178  */
      179 static const char *parentPath;
      180 
      181 /**
      182  * Split, canonicalized version of parentPath
      183  */
      184 static const char * const *parentPathv;
      185 
      186 static jfieldID field_exitcode;
      187 
      188 JNIEXPORT void JNICALL
      189 Java_java_lang_UNIXProcess_initIDs(JNIEnv *env, jclass clazz)
      190 {
      191     field_exitcode = (*env)->GetFieldID(env, clazz, "exitcode", "I");
      192 
      193     parentPath  = effectivePath();
      194     parentPathv = splitPath(env, parentPath);
      195 
      196     setSIGCHLDHandler(env);
      197 }
      198 
      199 
      200 #ifndef WIFEXITED
      201 #define WIFEXITED(status) (((status)&0xFF) == 0)
      202 #endif
      203 
      204 #ifndef WEXITSTATUS
      205 #define WEXITSTATUS(status) (((status)>>8)&0xFF)
      206 #endif
      207 
      208 #ifndef WIFSIGNALED
      209 #define WIFSIGNALED(status) (((status)&0xFF) > 0 && ((status)&0xFF00) == 0)
      210 #endif
      211 
      212 #ifndef WTERMSIG
      213 #define WTERMSIG(status) ((status)&0x7F)
      214 #endif
      215 
      216 /* Block until a child process exits and return its exit code.
      217    Note, can only be called once for any given pid. */
      218 JNIEXPORT jint JNICALL
      219 Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env,
      220                                               jobject junk,
      221                                               jint pid)
      222 {
      223     /* We used to use waitid() on Solaris, waitpid() on Linux, but
      224      * waitpid() is more standard, so use it on all POSIX platforms. */
      225     int status;
      226     /* Wait for the child process to exit.  This returns immediately if
      227        the child has already exited. */
      228     while (waitpid(pid, &status, 0) < 0) {
      229         switch (errno) {
      230         case ECHILD: return 0;
      231         case EINTR: break;
      232         default: return -1;
      233         }
      234     }
      235 
      236     if (WIFEXITED(status)) {
      237         /*
      238          * The child exited normally; get its exit code.
      239          */
      240         return WEXITSTATUS(status);
      241     } else if (WIFSIGNALED(status)) {
      242         /* The child exited because of a signal.
      243          * The best value to return is 0x80 + signal number,
      244          * because that is what all Unix shells do, and because
      245          * it allows callers to distinguish between process exit and
      246          * process death by signal.
      247          * Unfortunately, the historical behavior on Solaris is to return
      248          * the signal number, and we preserve this for compatibility. */
      249 #ifdef __solaris__
      250         return WTERMSIG(status);
      251 #else
      252         return 0x80 + WTERMSIG(status);
      253 #endif
      254     } else {
      255         /*
      256          * Unknown exit code; pass it through.
      257          */
      258         return status;
      259     }
      260 }
      261 
      262 static int
      263 closeDescriptors(void)
      264 {
      265     DIR *dp;
      266     struct dirent64 *dirp;
      267     int from_fd = FAIL_FILENO + 1;
      268 
      269     /* We're trying to close all file descriptors, but opendir() might
      270      * itself be implemented using a file descriptor, and we certainly
      271      * don't want to close that while it's in use.  We assume that if
      272      * opendir() is implemented using a file descriptor, then it uses
      273      * the lowest numbered file descriptor, just like open().  So we
      274      * close a couple explicitly.  */
      275 
      276     close(from_fd);             /* for possible use by opendir() */
      277     close(from_fd + 1);         /* another one for good luck */
      278 
      279     if ((dp = opendir("/proc/self/fd")) == NULL)
      280         return 0;
      281 
      282     /* We use readdir64 instead of readdir to work around Solaris bug
      283      * 6395699: /proc/self/fd fails to report file descriptors >= 1024 on Solaris 9
      284      */
      285     while ((dirp = readdir64(dp)) != NULL) {
      286         int fd;
      287         if (isdigit(dirp->d_name[0]) &&
      288             (fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2)
      289             close(fd);
      290     }
      291 
      292     closedir(dp);
      293 
      294     return 1;
      295 }
      296 
      297 static void
      298 moveDescriptor(int fd_from, int fd_to)
      299 {
      300     if (fd_from != fd_to) {
      301         dup2(fd_from, fd_to);
      302         close(fd_from);
      303     }
      304 }
      305 
      306 static const char *
      307 getBytes(JNIEnv *env, jbyteArray arr)
      308 {
      309     return arr == NULL ? NULL :
      310         (const char*) (*env)->GetByteArrayElements(env, arr, NULL);
      311 }
      312 
      313 static void
      314 releaseBytes(JNIEnv *env, jbyteArray arr, const char* parr)
      315 {
      316     if (parr != NULL)
      317         (*env)->ReleaseByteArrayElements(env, arr, (jbyte*) parr, JNI_ABORT);
      318 }
      319 
      320 static void
      321 initVectorFromBlock(const char**vector, const char* block, int count)
      322 {
      323     int i;
      324     const char *p;
      325     for (i = 0, p = block; i < count; i++) {
      326         /* Invariant: p always points to the start of a C string. */
      327         vector[i] = p;
      328         while (*(p++));
      329     }
      330     vector[count] = NULL;
      331 }
      332 
      333 static void
      334 throwIOException(JNIEnv *env, int errnum, const char *defaultDetail)
      335 {
      336     static const char * const format = "error=%d, %s";
      337     const char *detail = defaultDetail;
      338     char *errmsg;
      339     if (errnum != 0) {
      340         const char *s = strerror(errnum);
      341         if (strcmp(s, "Unknown error") != 0)
      342             detail = s;
      343     }
      344     /* ASCII Decimal representation uses 2.4 times as many bits as binary. */
      345     errmsg = NEW(char, strlen(format) + strlen(detail) + 3 * sizeof(errnum));
      346     sprintf(errmsg, format, errnum, detail);
      347     JNU_ThrowIOException(env, errmsg);
      348     free(errmsg);
      349 }
      350 
      351 #ifdef DEBUG_PROCESS
      352 /* Debugging process code is difficult; where to write debug output? */
      353 static void
      354 debugPrint(char *format, ...)
      355 {
      356     FILE *tty = fopen("/dev/tty", "w");
      357     va_list ap;
      358     va_start(ap, format);
      359     vfprintf(tty, format, ap);
      360     va_end(ap);
      361     fclose(tty);
      362 }
      363 #endif /* DEBUG_PROCESS */
      364 
      365 /* Version of execvpe when child's PATH differs from parent's */
      366 static int
      367 execvp_usingParentPath(const char *file, const char *const argv[])
      368 {
      369     char expanded_file[PATH_MAX];
      370     int filelen = strlen(file);
      371     int sticky_errno = 0;
      372     const char * const * dirs;
      373     /* Search parent's PATH */
      374     for (dirs = parentPathv; *dirs; dirs++) {
      375         const char * dir = *dirs;
      376         int dirlen = strlen(dir);
      377         if (filelen + dirlen + 1 >= PATH_MAX) {
      378             /* Resist the urge to remove this limit;
      379              * calling malloc after fork is unsafe. */
      380             errno = ENAMETOOLONG;
      381             continue;
      382         }
      383         strcpy(expanded_file, dir);
      384         strcpy(expanded_file + dirlen, file);
      385         execvp(expanded_file, (char **) argv);
      386         /* There are 3 responses to various classes of errno:
      387          * return immediately, continue (especially for ENOENT),
      388          * or continue with "sticky" errno.
      389          *
      390          * From exec(3):
      391          *
      392          * If permission is denied for a file (the attempted
      393          * execve returned EACCES), these functions will continue
      394          * searching the rest of the search path.  If no other
      395          * file is found, however, they will return with the
      396          * global variable errno set to EACCES.
      397          */
      398         switch (errno) {
      399         case EACCES:
      400             sticky_errno = errno;
      401             /* FALLTHRU */
      402         case ENOENT:
      403         case ENOTDIR:
      404 #ifdef ELOOP
      405         case ELOOP:
      406 #endif
      407 #ifdef ESTALE
      408         case ESTALE:
      409 #endif
      410 #ifdef ENODEV
      411         case ENODEV:
      412 #endif
      413 #ifdef ETIMEDOUT
      414         case ETIMEDOUT:
      415 #endif
      416             break; /* Try other directories in PATH */
      417         default:
      418             return -1;
      419         }
      420     }
      421     if (sticky_errno != 0)
      422         errno = sticky_errno;
      423     return -1;
      424 }
      425 
      426 /**
      427  * 'execvpe' should have been included in the Unix standards,
      428  * and is a GNU extension in glibc 2.10.
      429  *
      430  * JDK_execvpe is identical to execvp, except that the child environment is
      431  * specified via the 3rd argument instead of being inherited from environ.
      432  *
      433  * This implementation of JDK_execvpe does not work if memory is shared
      434  * with the parent, when using vfork(2), or clone(2) with CLONE_VM.
      435  */
      436 static int
      437 JDK_execvpe(const char *file,
      438             const char *const argv[],
      439             const char *const envp[])
      440 {
      441     /* This is one of the rare times it's more portable to declare an
      442      * external symbol explicitly, rather than via a system header.
      443      * The declaration is standardized as part of UNIX98, but there is
      444      * no standard (not even de-facto) header file where the
      445      * declaration is to be found.  See:
      446      * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
      447      * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
      448      *
      449      * "All identifiers in this volume of IEEE Std 1003.1-2001, except
      450      * environ, are defined in at least one of the headers" (!)
      451      */
      452     extern char **environ;
      453 
      454     if (envp != NULL)
      455         environ = (char **) envp;
      456 
      457     if (/* Parent and child environment the same?  Use child PATH. */
      458         (envp == NULL)
      459 
      460         /* http://www.opengroup.org/onlinepubs/009695399/functions/exec.html
      461          * "If the file argument contains a slash character, it is used as
      462          * the pathname for this file.  Otherwise, the path prefix for this
      463          * file is obtained by a search of the directories passed in the
      464          * PATH environment variable" */
      465         || (strchr(file, '/') != NULL)
      466 
      467         /* Parent and child PATH the same?  Use child PATH. */
      468         || (strcmp(parentPath, effectivePath()) == 0)
      469 
      470         /* We want ENOENT, not EACCES, for zero-length program names. */
      471         || (*file == '\0'))
      472 
      473         return execvp(file, (char **) argv);
      474     else
      475         return execvp_usingParentPath(file, argv);
      476 }
      477 
      478 static void
      479 closeSafely(int fd)
      480 {
      481     if (fd != -1)
      482         close(fd);
      483 }
      484 
      485 /*
      486  * Reads nbyte bytes from file descriptor fd into buf,
      487  * The read operation is retried in case of EINTR or partial reads.
      488  *
      489  * Returns number of bytes read (normally nbyte, but may be less in
      490  * case of EOF).  In case of read errors, returns -1 and sets errno.
      491  */
      492 static ssize_t
      493 readFully(int fd, void *buf, size_t nbyte)
      494 {
      495     ssize_t remaining = nbyte;
      496     for (;;) {
      497         ssize_t n = read(fd, buf, remaining);
      498         if (n == 0) {
      499             return nbyte - remaining;
      500         } else if (n > 0) {
      501             remaining -= n;
      502             if (remaining <= 0)
      503                 return nbyte;
      504             /* We were interrupted in the middle of reading the bytes.
      505              * Unlikely, but possible. */
      506             buf = (void *) (((char *)buf) + n);
      507         } else if (errno == EINTR) {
      508             /* Strange signals like SIGJVM1 are possible at any time.
      509              * See http://www.dreamsongs.com/WorseIsBetter.html */
      510         } else {
      511             return -1;
      512         }
      513     }
      514 }
      515 
      516 #ifndef __solaris__
      517 #undef fork1
      518 #define fork1() fork()
      519 #endif
      520 
      521 JNIEXPORT jint JNICALL
      522 Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
      523                                        jobject process,
      524                                        jbyteArray prog,
      525                                        jbyteArray argBlock, jint argc,
      526                                        jbyteArray envBlock, jint envc,
      527                                        jbyteArray dir,
      528                                        jboolean redirectErrorStream,
      529                                        jobject stdin_fd,
      530                                        jobject stdout_fd,
      531                                        jobject stderr_fd)
      532 {
      533     int errnum;
      534     int resultPid = -1;
      535     int in[2], out[2], err[2], fail[2];
      536     const char **argv = NULL;
      537     const char **envv = NULL;
      538     const char *pprog     = getBytes(env, prog);
      539     const char *pargBlock = getBytes(env, argBlock);
      540     const char *penvBlock = getBytes(env, envBlock);
      541     const char *pdir      = getBytes(env, dir);
      542 
      543     in[0] = in[1] = out[0] = out[1] = err[0] = err[1] = fail[0] = fail[1] = -1;
      544 
      545     assert(prog != NULL && argBlock != NULL);
      546     if (pprog     == NULL) goto Catch;
      547     if (pargBlock == NULL) goto Catch;
      548     if (envBlock  != NULL && penvBlock == NULL) goto Catch;
      549     if (dir       != NULL && pdir      == NULL) goto Catch;
      550 
      551     /* Convert pprog + pargBlock into a char ** argv */
      552     if ((argv = NEW(const char *, argc + 2)) == NULL)
      553         goto Catch;
      554     argv[0] = pprog;
      555     initVectorFromBlock(argv+1, pargBlock, argc);
      556 
      557     if (envBlock != NULL) {
      558         /* Convert penvBlock into a char ** envv */
      559         if ((envv = NEW(const char *, envc + 1)) == NULL)
      560             goto Catch;
      561         initVectorFromBlock(envv, penvBlock, envc);
      562     }
      563 
      564     if ((pipe(in)   < 0) ||
      565         (pipe(out)  < 0) ||
      566         (pipe(err)  < 0) ||
      567         (pipe(fail) < 0)) {
      568         throwIOException(env, errno, "Bad file descriptor");
      569         goto Catch;
      570     }
      571 
      572     resultPid = fork1();
      573     if (resultPid < 0) {
      574         throwIOException(env, errno, "Fork failed");
      575         goto Catch;
      576     }
      577 
      578     if (resultPid == 0) {
      579         /* Child process */
      580 
      581         /* Close the parent sides of the pipe.
      582            Give the child sides of the pipes the right fileno's.
      583            Closing pipe fds here is redundant, since closeDescriptors()
      584            would do it anyways, but a little paranoia is a good thing. */
      585         /* Note: it is possible for in[0] == 0 */
      586         close(in[1]);
      587         moveDescriptor(in[0], STDIN_FILENO);
      588         close(out[0]);
      589         moveDescriptor(out[1], STDOUT_FILENO);
      590         close(err[0]);
      591         if (redirectErrorStream) {
      592             close(err[1]);
      593             dup2(STDOUT_FILENO, STDERR_FILENO);
      594         } else {
      595             moveDescriptor(err[1], STDERR_FILENO);
      596         }
      597         close(fail[0]);
      598         moveDescriptor(fail[1], FAIL_FILENO);
      599 
      600         /* close everything */
      601         if (closeDescriptors() == 0) { /* failed,  close the old way */
      602             int max_fd = (int)sysconf(_SC_OPEN_MAX);
      603             int i;
      604             for (i = FAIL_FILENO + 1; i < max_fd; i++)
      605                 close(i);
      606         }
      607 
      608         /* change to the new working directory */
      609         if (pdir != NULL && chdir(pdir) < 0)
      610             goto WhyCantJohnnyExec;
      611 
      612         if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1)
      613             goto WhyCantJohnnyExec;
      614 
      615         JDK_execvpe(argv[0], argv, envv);
      616 
      617     WhyCantJohnnyExec:
      618         /* We used to go to an awful lot of trouble to predict whether the
      619          * child would fail, but there is no reliable way to predict the
      620          * success of an operation without *trying* it, and there's no way
      621          * to try a chdir or exec in the parent.  Instead, all we need is a
      622          * way to communicate any failure back to the parent.  Easy; we just
      623          * send the errno back to the parent over a pipe in case of failure.
      624          * The tricky thing is, how do we communicate the *success* of exec?
      625          * We use FD_CLOEXEC together with the fact that a read() on a pipe
      626          * yields EOF when the write ends (we have two of them!) are closed.
      627          */
      628         errnum = errno;
      629         write(FAIL_FILENO, &errnum, sizeof(errnum));
      630         close(FAIL_FILENO);
      631         _exit(-1);
      632     }
      633 
      634     /* parent process */
      635 
      636     close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */
      637 
      638     switch (readFully(fail[0], &errnum, sizeof(errnum))) {
      639     case 0: break; /* Exec succeeded */
      640     case sizeof(errnum):
      641         waitpid(resultPid, NULL, 0);
      642         throwIOException(env, errnum, "Exec failed");
      643         goto Catch;
      644     default:
      645         throwIOException(env, errno, "Read failed");
      646         goto Catch;
      647     }
      648 
      649     (*env)->SetIntField(env, stdin_fd,  IO_fd_fdID, in [1]);
      650     (*env)->SetIntField(env, stdout_fd, IO_fd_fdID, out[0]);
      651     (*env)->SetIntField(env, stderr_fd, IO_fd_fdID, err[0]);
      652 
      653  Finally:
      654     /* Always clean up the child's side of the pipes */
      655     closeSafely(in [0]);
      656     closeSafely(out[1]);
      657     closeSafely(err[1]);
      658 
      659     /* Always clean up fail descriptors */
      660     closeSafely(fail[0]);
      661     closeSafely(fail[1]);
      662 
      663     free(argv);
      664     free(envv);
      665 
      666     releaseBytes(env, prog,     pprog);
      667     releaseBytes(env, argBlock, pargBlock);
      668     releaseBytes(env, envBlock, penvBlock);
      669     releaseBytes(env, dir,      pdir);
      670 
      671     return resultPid;
      672 
      673  Catch:
      674     /* Clean up the parent's side of the pipes in case of failure only */
      675     closeSafely(in [1]);
      676     closeSafely(out[0]);
      677     closeSafely(err[0]);
      678     goto Finally;
      679 }
      680 
      681 JNIEXPORT void JNICALL
      682 Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env, jobject junk, jint pid)
      683 {
      684     kill(pid, SIGTERM);
      685 }