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