⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 posixprocess.java

📁 gcc的组建
💻 JAVA
字号:
// PosixProcess.java - Subclass of Process for POSIX systems./* Copyright (C) 1998, 1999, 2004  Free Software Foundation   This file is part of libgcj.This software is copyrighted work licensed under the terms of theLibgcj License.  Please consult the file "LIBGCJ_LICENSE" fordetails.  */package java.lang;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.HashMap;import java.util.LinkedList;import java.util.List;import java.util.Map;/** * @author Tom Tromey <tromey@cygnus.com> * @date May 3, 1999 * @author David Daney <ddaney@avtrex.com> Rewrote using * ProcessManager */// This is entirely internal to our implementation.// This file is copied to `ConcreteProcess.java' before compilation.// Hence the class name apparently does not match the file name.final class ConcreteProcess extends Process{  static class ProcessManager extends Thread  {    /**     * A list of {@link ConcreteProcess ConcreteProcesses} to be     * started.  The queueLock object is used as the lock Object     * for all process related operations. To avoid dead lock     * ensure queueLock is obtained before ConcreteProcess.     */    List queue = new LinkedList();    private Map pidToProcess = new HashMap();    private boolean ready = false;    private long reaperPID;    ProcessManager()    {      super("ProcessManager");      // Don't keep the (main) process from exiting on our account.      this.setDaemon(true);    }    /**     * Get the ConcreteProcess object with the given pid and     * remove it from the map.  This method is called from the     * native code for {@link #reap()).  The mapping is removed so     * the ConcreteProcesses can be GCed after they terminate.     *     * @param p The pid of the process.     */    private ConcreteProcess removeProcessFromMap(long p)    {      return (ConcreteProcess) pidToProcess.remove(new Long(p));    }    /**     * Put the given ConcreteProcess in the map using the Long     * value of its pid as the key.     *     * @param p The ConcreteProcess.     */    void addProcessToMap(ConcreteProcess p)    {      pidToProcess.put(new Long(p.pid), p);    }    /**     * Queue up the ConcreteProcess and awake the ProcessManager.     * The ProcessManager will start the ConcreteProcess from its     * thread so it can be reaped when it terminates.     *     * @param p The ConcreteProcess.     */    void startExecuting(ConcreteProcess p)    {      synchronized (queueLock)        {	  queue.add(p);	  signalReaper(); // If blocked in waitForSignal().	  queueLock.notifyAll(); // If blocked in wait();        }    }    /**     * Block until the ProcessManager thread is ready to accept     * commands.     */    void waitUntilReady()    {      synchronized (this)        {	  try	    {	      while (! ready)		wait();	    }	  catch (InterruptedException ie)	    {	      // Ignore.	    }        }    }    /**     * Main Process starting/reaping loop.     */    public void run()    {      init();      // Now ready to accept requests.      synchronized (this)        {	  ready = true;	  this.notifyAll();        }      for (;;)        {	  try	    {	      synchronized (queueLock)	        {		  boolean haveMoreChildren = reap();		  if (! haveMoreChildren && queue.size() == 0)		    {		      // This reaper thread could exit, but we		      // keep it alive for a while in case		      // someone wants to start more Processes.		      try		        {			  queueLock.wait(1000L);			  if (queue.size() == 0)			    {			      processManager = null;			      return; // Timed out.			    }		        }		      catch (InterruptedException ie)		        {			  // Ignore and exit the thread.			  return;		        }		    }		  while (queue.size() > 0)		    {		      ConcreteProcess p = (ConcreteProcess) queue.remove(0);		      p.spawn(this);		    }	        }	      // Wait for a SIGCHLD from either an exiting	      // process or the startExecuting() method.  This	      // is done outside of the synchronized block to	      // allow other threads to enter and submit more	      // jobs.	      waitForSignal();	    }	  catch (Exception ex)	    {	      ex.printStackTrace(System.err);	    }        }    }    /**     * Setup native signal handlers and other housekeeping things.     *     */    private native void init();    /**     * Block waiting for SIGCHLD.     *     */    private native void waitForSignal();    /**     * Try to reap as many children as possible without blocking.     *     * @return true if more live children exist.     *     */    private native boolean reap();    /**     * Send SIGCHLD to the reaper thread.     */    private native void signalReaper();  }  public void destroy()  {    // Synchronized on the queueLock.  This ensures that the reaper    // thread cannot be doing a wait() on the child.    // Otherwise there would be a race where the OS could    // create a process with the same pid between the wait()    // and the update of the state which would cause a kill to    // the wrong process.    synchronized (queueLock)      {	synchronized (this)	  {	    // If there is no ProcessManager we cannot kill.	    if (state != STATE_TERMINATED)	      {		if (processManager == null)		  throw new InternalError();		nativeDestroy();	      }	  }      }  }  private native void nativeDestroy();  public int exitValue()  {    synchronized (this)      {	if (state != STATE_TERMINATED)	  throw new IllegalThreadStateException("Process has not exited");      }    return status;  }  /**   * Called by native code when process exits.   *   * Already synchronized (this).  Close any streams that we can to   * conserve file descriptors.   *   * The outputStream can be closed as any future writes will   * generate an IOException due to EPIPE.   *   * The inputStream and errorStream can only be closed if the user   * has not obtained a reference to them AND they have no bytes   * available.  Since the process has terminated they will never have   * any more data available and can safely be replaced by   * EOFInputStreams.   */  void processTerminationCleanup()  {    try      {        outputStream.close();      }    catch (IOException ioe)      {        // Ignore.      }    try      {        if (returnedErrorStream == null && errorStream.available() == 0)          {            errorStream.close();            errorStream = null;          }      }    catch (IOException ioe)      {        // Ignore.      }    try      {        if (returnedInputStream == null && inputStream.available() == 0)          {            inputStream.close();            inputStream = null;          }      }    catch (IOException ioe)      {        // Ignore.      }  }  public synchronized InputStream getErrorStream()  {    if (returnedErrorStream != null)      return returnedErrorStream;    if (errorStream == null)      returnedErrorStream = EOFInputStream.instance;    else      returnedErrorStream = errorStream;                return returnedErrorStream;  }  public synchronized InputStream getInputStream()  {    if (returnedInputStream != null)      return returnedInputStream;    if (inputStream == null)      returnedInputStream = EOFInputStream.instance;    else      returnedInputStream = inputStream;                return returnedInputStream;  }  public OutputStream getOutputStream()  {    return outputStream;  }  public int waitFor() throws InterruptedException  {    synchronized (this)      {	while (state != STATE_TERMINATED)	  wait();      }    return status;  }  /**   * Start this process running.  This should only be called by the   * ProcessManager.   *   * @param pm The ProcessManager that made the call.   */  void spawn(ProcessManager pm)  {    synchronized (this)      {	// Do the fork/exec magic.	nativeSpawn();	// There is no race with reap() in the pidToProcess map	// because this is always called from the same thread	// doing the reaping.	pm.addProcessToMap(this);	state = STATE_RUNNING;	// Notify anybody waiting on state change.	this.notifyAll();      }  }  /**   * Do the fork and exec.   */  private native void nativeSpawn();  // This file is copied to `ConcreteProcess.java' before  // compilation.  Hence the constructor name apparently does not  // match the file name.  ConcreteProcess(String[] progarray, String[] envp, File dir)           throws IOException  {    // Check to ensure there is something to run, and avoid    // dereferencing null pointers in native code.    if (progarray[0] == null)      throw new NullPointerException();    this.progarray = progarray;    this.envp = envp;    this.dir = dir;    // Start a ProcessManager if there is not one already running.    synchronized (queueLock)      {	if (processManager == null)	  {	    processManager = new ProcessManager();	    processManager.start();	    processManager.waitUntilReady();	  }	// Queue this ConcreteProcess for starting by the ProcessManager.	processManager.startExecuting(this);      }    // Wait until ProcessManager has started us.    synchronized (this)      {	while (state == STATE_WAITING_TO_START)	  {	    try	      {		wait();	      }	    catch (InterruptedException ie)	      {		// FIXME: What to do when interrupted while blocking in a constructor?		// Ignore.	      }	  }      }    // If there was a problem, re-throw it.    if (exception != null)      {	if (exception instanceof IOException)	  {	    IOException ioe = new IOException(exception.toString());	    ioe.initCause(exception);	    throw ioe;	  }	// Not an IOException.  Something bad happened.	InternalError ie = new InternalError(exception.toString());	ie.initCause(exception);	throw ie;      }    // If we get here, all is well, the Process has started.  }  private String[] progarray;  private String[] envp;  private File dir;  /** Set by the ProcessManager on problems starting. */  private Throwable exception;  /** The process id.  This is cast to a pid_t on the native side. */  private long pid;  // FIXME: Why doesn't the friend declaration in ConcreteProcess.h  // allow ConcreteProcess$ProcessManager native code access these  // when they are private?  /** Before the process is forked. */  static final int STATE_WAITING_TO_START = 0;  /** After the fork. */  static final int STATE_RUNNING = 1;  /** After exit code has been collected. */  static final int STATE_TERMINATED = 2;  /** One of STATE_WAITING_TO_START, STATE_RUNNING, STATE_TERMINATED. */  int state;  /** The exit status, if the child has exited. */  int status;  /** The streams. */  private InputStream errorStream;  private InputStream inputStream;  private OutputStream outputStream;  /** InputStreams obtained by the user.  Not null indicates that the   *  user has obtained the stream.   */  private InputStream returnedErrorStream;  private InputStream returnedInputStream;  /**   * Lock Object for all processManager related locking.   */  private static Object queueLock = new Object();  private static ProcessManager processManager;  static class EOFInputStream extends InputStream  {    static EOFInputStream instance = new EOFInputStream();    public int read()    {      return -1;    }  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -