jdk/src/solaris/classes/java/lang/UNIXProcess.java.bsd
author michaelm
Tue, 06 Mar 2012 20:34:38 +0000
changeset 12047 320a714614e9
child 13149 27d52f97a5cc
permissions -rw-r--r--
7113349: Initial changeset for Macosx port to jdk Reviewed-by: jjh, alanb, dholmes, anthony, ohrstrom, ksrini, jrose, weijun, smarks Contributed-by: Alan Bateman <alan.bateman@oracle.com>, Alexander Potochkin <alexander.potochkin@oracle.com>, Alexander Zuev <alexander.zuev@oracle.com>, Andrew Brygin <andrew.brygin@oracle.com>, Artem Ananiev <artem.ananiev@oracle.com>, Alex Strange <astrange@apple.com>, Bino George <bino@apple.com>, Christine Lu <christine.lu@oracle.com>, David Katleman <david.katleman@oracle.com>, David Durrence <david_durrence@apple.com>, Dmitry Cherepanov <dmitry.cherepanov@oracle.com>, Greg Lewis <glewis@eyesbeyond.com>, Kevin Miller <kevin_m_miller@apple.com>, Kurt Miller <kurt@intricatesoftware.com>, Landon Fuller <landonf@plausiblelabs.com>, Leonid Romanov <leonid.romanov@oracle.com>, Loefty Walkowiak <loefty@apple.com>, Mark Reinhold <mark.reinhold@oracle.com>, Naoto Sato <naoto.sato@oracle.com>, Philip Race <philip.race@oracle.com>, Roger Hoover <rhoover@apple.com>, Scott Kovatch <scott.kovatch@oracle.com>, Sergey ByloKhov <sergey.bylokhov@oracle.com>, Mike Swingler <swingler@apple.com>, Tomas Hurka <tomas.hurka@oracle.com>
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
12047
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     1
/*
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     2
 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     4
 *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    10
 *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    15
 * accompanied this code).
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    16
 *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    20
 *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    23
 * questions.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    24
 */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    25
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    26
package java.lang;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    27
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    28
import java.io.BufferedInputStream;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    29
import java.io.BufferedOutputStream;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    30
import java.io.ByteArrayInputStream;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    31
import java.io.FileDescriptor;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    32
import java.io.FileInputStream;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    33
import java.io.FileOutputStream;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    34
import java.io.IOException;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    35
import java.io.InputStream;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    36
import java.io.OutputStream;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    37
import java.util.Arrays;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    38
import java.util.concurrent.Executors;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    39
import java.util.concurrent.Executor;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    40
import java.util.concurrent.ThreadFactory;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    41
import java.security.AccessController;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    42
import static java.security.AccessController.doPrivileged;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    43
import java.security.PrivilegedAction;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    44
import java.security.PrivilegedActionException;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    45
import java.security.PrivilegedExceptionAction;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    46
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    47
/**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    48
 * java.lang.Process subclass in the UNIX environment.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    49
 *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    50
 * @author Mario Wolczko and Ross Knippel.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    51
 * @author Konstantin Kladko (ported to Bsd)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    52
 * @author Martin Buchholz
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    53
 */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    54
final class UNIXProcess extends Process {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    55
    private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    56
        = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    57
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    58
    private final int pid;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    59
    private int exitcode;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    60
    private boolean hasExited;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    61
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    62
    private /* final */ OutputStream stdin;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    63
    private /* final */ InputStream  stdout;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    64
    private /* final */ InputStream  stderr;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    65
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    66
    /* this is for the reaping thread */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    67
    private native int waitForProcessExit(int pid);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    68
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    69
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    70
     * Create a process using fork(2) and exec(2).
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    71
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    72
     * @param fds an array of three file descriptors.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    73
     *        Indexes 0, 1, and 2 correspond to standard input,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    74
     *        standard output and standard error, respectively.  On
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    75
     *        input, a value of -1 means to create a pipe to connect
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    76
     *        child and parent processes.  On output, a value which
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    77
     *        is not -1 is the parent pipe fd corresponding to the
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    78
     *        pipe which has been created.  An element of this array
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    79
     *        is -1 on input if and only if it is <em>not</em> -1 on
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    80
     *        output.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    81
     * @return the pid of the subprocess
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    82
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    83
    private native int forkAndExec(byte[] prog,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    84
                                   byte[] argBlock, int argc,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    85
                                   byte[] envBlock, int envc,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    86
                                   byte[] dir,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    87
                                   int[] fds,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    88
                                   boolean redirectErrorStream)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    89
        throws IOException;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    90
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    91
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    92
     * The thread factory used to create "process reaper" daemon threads.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    93
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    94
    private static class ProcessReaperThreadFactory implements ThreadFactory {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    95
        private final static ThreadGroup group = getRootThreadGroup();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    96
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    97
        private static ThreadGroup getRootThreadGroup() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    98
            return doPrivileged(new PrivilegedAction<ThreadGroup> () {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
    99
                public ThreadGroup run() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   100
                    ThreadGroup root = Thread.currentThread().getThreadGroup();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   101
                    while (root.getParent() != null)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   102
                        root = root.getParent();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   103
                    return root;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   104
                }});
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   105
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   106
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   107
        public Thread newThread(Runnable grimReaper) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   108
            // Our thread stack requirement is quite modest.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   109
            Thread t = new Thread(group, grimReaper, "process reaper", 32768);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   110
            t.setDaemon(true);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   111
            // A small attempt (probably futile) to avoid priority inversion
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   112
            t.setPriority(Thread.MAX_PRIORITY);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   113
            return t;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   114
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   115
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   116
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   117
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   118
     * The thread pool of "process reaper" daemon threads.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   119
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   120
    private static final Executor processReaperExecutor =
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   121
        doPrivileged(new PrivilegedAction<Executor>() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   122
            public Executor run() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   123
                return Executors.newCachedThreadPool
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   124
                    (new ProcessReaperThreadFactory());
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   125
            }});
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   126
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   127
    UNIXProcess(final byte[] prog,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   128
                final byte[] argBlock, final int argc,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   129
                final byte[] envBlock, final int envc,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   130
                final byte[] dir,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   131
                final int[] fds,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   132
                final boolean redirectErrorStream)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   133
            throws IOException {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   134
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   135
        pid = forkAndExec(prog,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   136
                          argBlock, argc,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   137
                          envBlock, envc,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   138
                          dir,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   139
                          fds,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   140
                          redirectErrorStream);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   141
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   142
        try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   143
            doPrivileged(new PrivilegedExceptionAction<Void>() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   144
                public Void run() throws IOException {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   145
                    initStreams(fds);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   146
                    return null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   147
                }});
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   148
        } catch (PrivilegedActionException ex) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   149
            throw (IOException) ex.getException();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   150
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   151
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   152
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   153
    static FileDescriptor newFileDescriptor(int fd) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   154
        FileDescriptor fileDescriptor = new FileDescriptor();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   155
        fdAccess.set(fileDescriptor, fd);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   156
        return fileDescriptor;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   157
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   158
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   159
    void initStreams(int[] fds) throws IOException {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   160
        stdin = (fds[0] == -1) ?
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   161
            ProcessBuilder.NullOutputStream.INSTANCE :
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   162
            new ProcessPipeOutputStream(fds[0]);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   163
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   164
        stdout = (fds[1] == -1) ?
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   165
            ProcessBuilder.NullInputStream.INSTANCE :
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   166
            new ProcessPipeInputStream(fds[1]);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   167
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   168
        stderr = (fds[2] == -1) ?
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   169
            ProcessBuilder.NullInputStream.INSTANCE :
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   170
            new ProcessPipeInputStream(fds[2]);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   171
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   172
        processReaperExecutor.execute(new Runnable() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   173
            public void run() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   174
                int exitcode = waitForProcessExit(pid);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   175
                UNIXProcess.this.processExited(exitcode);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   176
            }});
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   177
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   178
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   179
    void processExited(int exitcode) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   180
        synchronized (this) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   181
            this.exitcode = exitcode;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   182
            hasExited = true;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   183
            notifyAll();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   184
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   185
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   186
        if (stdout instanceof ProcessPipeInputStream)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   187
            ((ProcessPipeInputStream) stdout).processExited();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   188
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   189
        if (stderr instanceof ProcessPipeInputStream)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   190
            ((ProcessPipeInputStream) stderr).processExited();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   191
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   192
        if (stdin instanceof ProcessPipeOutputStream)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   193
            ((ProcessPipeOutputStream) stdin).processExited();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   194
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   195
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   196
    public OutputStream getOutputStream() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   197
        return stdin;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   198
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   199
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   200
    public InputStream getInputStream() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   201
        return stdout;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   202
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   203
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   204
    public InputStream getErrorStream() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   205
        return stderr;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   206
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   207
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   208
    public synchronized int waitFor() throws InterruptedException {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   209
        while (!hasExited) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   210
            wait();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   211
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   212
        return exitcode;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   213
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   214
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   215
    public synchronized int exitValue() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   216
        if (!hasExited) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   217
            throw new IllegalThreadStateException("process hasn't exited");
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   218
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   219
        return exitcode;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   220
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   221
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   222
    private static native void destroyProcess(int pid);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   223
    public void destroy() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   224
        // There is a risk that pid will be recycled, causing us to
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   225
        // kill the wrong process!  So we only terminate processes
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   226
        // that appear to still be running.  Even with this check,
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   227
        // there is an unavoidable race condition here, but the window
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   228
        // is very small, and OSes try hard to not recycle pids too
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   229
        // soon, so this is quite safe.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   230
        synchronized (this) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   231
            if (!hasExited)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   232
                destroyProcess(pid);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   233
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   234
        try { stdin.close();  } catch (IOException ignored) {}
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   235
        try { stdout.close(); } catch (IOException ignored) {}
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   236
        try { stderr.close(); } catch (IOException ignored) {}
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   237
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   238
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   239
    /* This routine initializes JNI field offsets for the class */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   240
    private static native void initIDs();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   241
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   242
    static {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   243
        initIDs();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   244
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   245
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   246
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   247
     * A buffered input stream for a subprocess pipe file descriptor
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   248
     * that allows the underlying file descriptor to be reclaimed when
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   249
     * the process exits, via the processExited hook.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   250
     *
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   251
     * This is tricky because we do not want the user-level InputStream to be
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   252
     * closed until the user invokes close(), and we need to continue to be
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   253
     * able to read any buffered data lingering in the OS pipe buffer.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   254
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   255
    static class ProcessPipeInputStream extends BufferedInputStream {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   256
        ProcessPipeInputStream(int fd) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   257
            super(new FileInputStream(newFileDescriptor(fd)));
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   258
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   259
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   260
        private static byte[] drainInputStream(InputStream in)
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   261
                throws IOException {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   262
            if (in == null) return null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   263
            int n = 0;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   264
            int j;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   265
            byte[] a = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   266
            while ((j = in.available()) > 0) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   267
                a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   268
                n += in.read(a, n, j);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   269
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   270
            return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   271
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   272
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   273
        /** Called by the process reaper thread when the process exits. */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   274
        synchronized void processExited() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   275
            // Most BufferedInputStream methods are synchronized, but close()
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   276
            // is not, and so we have to handle concurrent racing close().
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   277
            try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   278
                InputStream in = this.in;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   279
                if (in != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   280
                    byte[] stragglers = drainInputStream(in);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   281
                    in.close();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   282
                    this.in = (stragglers == null) ?
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   283
                        ProcessBuilder.NullInputStream.INSTANCE :
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   284
                        new ByteArrayInputStream(stragglers);
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   285
                    if (buf == null) // asynchronous close()?
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   286
                        this.in = null;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   287
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   288
            } catch (IOException ignored) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   289
                // probably an asynchronous close().
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   290
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   291
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   292
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   293
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   294
    /**
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   295
     * A buffered output stream for a subprocess pipe file descriptor
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   296
     * that allows the underlying file descriptor to be reclaimed when
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   297
     * the process exits, via the processExited hook.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   298
     */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   299
    static class ProcessPipeOutputStream extends BufferedOutputStream {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   300
        ProcessPipeOutputStream(int fd) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   301
            super(new FileOutputStream(newFileDescriptor(fd)));
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   302
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   303
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   304
        /** Called by the process reaper thread when the process exits. */
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   305
        synchronized void processExited() {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   306
            OutputStream out = this.out;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   307
            if (out != null) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   308
                try {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   309
                    out.close();
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   310
                } catch (IOException ignored) {
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   311
                    // We know of no reason to get an IOException, but if
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   312
                    // we do, there's nothing else to do but carry on.
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   313
                }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   314
                this.out = ProcessBuilder.NullOutputStream.INSTANCE;
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   315
            }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   316
        }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   317
    }
320a714614e9 7113349: Initial changeset for Macosx port to jdk
michaelm
parents:
diff changeset
   318
}