src/solaris/classes/java/lang/UNIXProcess.java.solaris

Print this page


   1 /*
   2  * Copyright (c) 1995, 2010, 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 package java.lang;
  27 
  28 import java.io.*;

  29 
  30 /* java.lang.Process subclass in the UNIX environment.
  31  *
  32  * @author Mario Wolczko and Ross Knippel.
  33  */
  34 
  35 final class UNIXProcess extends Process {
  36     private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
  37         = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
  38 
  39     private final int pid;
  40     private int exitcode;
  41     private boolean hasExited;
  42 
  43     private OutputStream stdin_stream;
  44     private InputStream stdout_stream;
  45     private DeferredCloseInputStream stdout_inner_stream;
  46     private InputStream stderr_stream;
  47 
  48     /* this is for the reaping thread */


 141 
 142     public OutputStream getOutputStream() {
 143         return stdin_stream;
 144     }
 145 
 146     public InputStream getInputStream() {
 147         return stdout_stream;
 148     }
 149 
 150     public InputStream getErrorStream() {
 151         return stderr_stream;
 152     }
 153 
 154     public synchronized int waitFor() throws InterruptedException {
 155         while (!hasExited) {
 156             wait();
 157         }
 158         return exitcode;
 159     }
 160 



















 161     public synchronized int exitValue() {
 162         if (!hasExited) {
 163             throw new IllegalThreadStateException("process hasn't exited");
 164         }
 165         return exitcode;
 166     }
 167 
 168     private static native void destroyProcess(int pid);
 169     public synchronized void destroy() {
 170         // There is a risk that pid will be recycled, causing us to
 171         // kill the wrong process!  So we only terminate processes
 172         // that appear to still be running.  Even with this check,
 173         // there is an unavoidable race condition here, but the window
 174         // is very small, and OSes try hard to not recycle pids too
 175         // soon, so this is quite safe.
 176         if (!hasExited)
 177             destroyProcess(pid);
 178         try {
 179             stdin_stream.close();
 180             if (stdout_inner_stream != null)
 181                 stdout_inner_stream.closeDeferred(stdout_stream);
 182             if (stderr_stream instanceof DeferredCloseInputStream)
 183                 ((DeferredCloseInputStream) stderr_stream)
 184                     .closeDeferred(stderr_stream);
 185         } catch (IOException e) {
 186             // ignore
 187         }
 188     }
 189 















 190     // A FileInputStream that supports the deferment of the actual close
 191     // operation until the last pending I/O operation on the stream has
 192     // finished.  This is required on Solaris because we must close the stdin
 193     // and stdout streams in the destroy method in order to reclaim the
 194     // underlying file descriptors.  Doing so, however, causes any thread
 195     // currently blocked in a read on one of those streams to receive an
 196     // IOException("Bad file number"), which is incompatible with historical
 197     // behavior.  By deferring the close we allow any pending reads to see -1
 198     // (EOF) as they did before.
 199     //
 200     private static class DeferredCloseInputStream
 201         extends FileInputStream
 202     {
 203 
 204         private DeferredCloseInputStream(FileDescriptor fd) {
 205             super(fd);
 206         }
 207 
 208         private Object lock = new Object();     // For the following fields
 209         private boolean closePending = false;


   1 /*
   2  * Copyright (c) 1995, 2012, 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 package java.lang;
  27 
  28 import java.io.*;
  29 import java.util.concurrent.TimeUnit;
  30 
  31 /* java.lang.Process subclass in the UNIX environment.
  32  *
  33  * @author Mario Wolczko and Ross Knippel.
  34  */
  35 
  36 final class UNIXProcess extends Process {
  37     private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
  38         = sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
  39 
  40     private final int pid;
  41     private int exitcode;
  42     private boolean hasExited;
  43 
  44     private OutputStream stdin_stream;
  45     private InputStream stdout_stream;
  46     private DeferredCloseInputStream stdout_inner_stream;
  47     private InputStream stderr_stream;
  48 
  49     /* this is for the reaping thread */


 142 
 143     public OutputStream getOutputStream() {
 144         return stdin_stream;
 145     }
 146 
 147     public InputStream getInputStream() {
 148         return stdout_stream;
 149     }
 150 
 151     public InputStream getErrorStream() {
 152         return stderr_stream;
 153     }
 154 
 155     public synchronized int waitFor() throws InterruptedException {
 156         while (!hasExited) {
 157             wait();
 158         }
 159         return exitcode;
 160     }
 161     
 162     @Override
 163     public synchronized boolean waitFor(long timeout, TimeUnit unit) 
 164         throws InterruptedException {
 165         if (hasExited) return true;
 166         if (timeout <= 0) return false;              
 167                 
 168         long now = System.nanoTime();
 169         long end = now + TimeUnit.NANOSECONDS.convert(timeout, unit);
 170         if (end <= 0) // overflow
 171             end = Long.MAX_VALUE;
 172         
 173         long rem = end - now;
 174         while (!hasExited && (rem > 0)) {
 175             wait(TimeUnit.NANOSECONDS.toMillis(rem));
 176             rem = end - System.nanoTime();
 177         }
 178         return hasExited;
 179     }
 180 
 181     public synchronized int exitValue() {
 182         if (!hasExited) {
 183             throw new IllegalThreadStateException("process hasn't exited");
 184         }
 185         return exitcode;
 186     }
 187 
 188     private static native void destroyProcess(int pid, boolean force);
 189     private synchronized void destroy(boolean force) {
 190         // There is a risk that pid will be recycled, causing us to
 191         // kill the wrong process!  So we only terminate processes
 192         // that appear to still be running.  Even with this check,
 193         // there is an unavoidable race condition here, but the window
 194         // is very small, and OSes try hard to not recycle pids too
 195         // soon, so this is quite safe.
 196         if (!hasExited)
 197             destroyProcess(pid, force);
 198         try {
 199             stdin_stream.close();
 200             if (stdout_inner_stream != null)
 201                 stdout_inner_stream.closeDeferred(stdout_stream);
 202             if (stderr_stream instanceof DeferredCloseInputStream)
 203                 ((DeferredCloseInputStream) stderr_stream)
 204                     .closeDeferred(stderr_stream);
 205         } catch (IOException e) {
 206             // ignore
 207         }
 208     }
 209 
 210     public void destroy() {
 211         destroy(false);
 212     }
 213 
 214     @Override
 215     public Process destroyForcibly() {
 216         destroy(true);
 217         return this;
 218     }
 219 
 220     @Override
 221     public synchronized boolean isAlive() {
 222         return !hasExited;
 223     }
 224 
 225     // A FileInputStream that supports the deferment of the actual close
 226     // operation until the last pending I/O operation on the stream has
 227     // finished.  This is required on Solaris because we must close the stdin
 228     // and stdout streams in the destroy method in order to reclaim the
 229     // underlying file descriptors.  Doing so, however, causes any thread
 230     // currently blocked in a read on one of those streams to receive an
 231     // IOException("Bad file number"), which is incompatible with historical
 232     // behavior.  By deferring the close we allow any pending reads to see -1
 233     // (EOF) as they did before.
 234     //
 235     private static class DeferredCloseInputStream
 236         extends FileInputStream
 237     {
 238 
 239         private DeferredCloseInputStream(FileDescriptor fd) {
 240             super(fd);
 241         }
 242 
 243         private Object lock = new Object();     // For the following fields
 244         private boolean closePending = false;