FileDocCategorySizeDatePackage
ProcessManager.javaAPI DocAndroid 1.5 API12106Wed May 06 22:41:04 BST 2009java.lang

ProcessManager

public final class ProcessManager extends Object
Manages child processes.

Harmony's native implementation (for comparison purposes): http://tinyurl.com/3ytwuq

Fields Summary
private static final int
WAIT_STATUS_UNKNOWN
constant communicated from native code indicating that a child died, but it was unable to determine the status
private static final int
WAIT_STATUS_NO_CHILDREN
constant communicated from native code indicating that there are currently no children to wait for
private static final int
WAIT_STATUS_STRANGE_ERRNO
constant communicated from native code indicating that a wait() call returned -1 and set an undocumented (and hence unexpected) errno
private final Map
processReferences
Map from pid to Process. We keep weak references to the Process objects and clean up the entries when no more external references are left. The process objects themselves don't require much memory, but file descriptors (associated with stdin/out/err in this case) can be a scarce resource.
private final ProcessReferenceQueue
referenceQueue
Keeps track of garbage-collected Processes.
static final ProcessManager
instance
Constructors Summary
private ProcessManager()


      
        // Spawn a thread to listen for signals from child processes.
        Thread processThread = new Thread(ProcessManager.class.getName()) {
            @Override
            public void run() {
                watchChildren();
            }
        };
        processThread.setDaemon(true);
        processThread.start();
    
Methods Summary
voidcleanUp()
Cleans up after garbage collected processes. Requires the lock on the map.

        ProcessReference reference;
        while ((reference = referenceQueue.poll()) != null) {
            synchronized (processReferences) {
                processReferences.remove(reference.processId);
            }
        }
    
private static native voidclose(java.io.FileDescriptor fd)
Closes the given file descriptor.

static native intexec(java.lang.String[] commands, java.lang.String[] environment, java.lang.String workingDirectory, java.io.FileDescriptor in, java.io.FileDescriptor out, java.io.FileDescriptor err)
Executes a native process. Fills in in, out, and err and returns the new process ID upon success.

java.lang.Processexec(java.lang.String[] commands, java.lang.String[] environment, java.io.File workingDirectory)
Executes a process and returns an object representing it.

        FileDescriptor in = new FileDescriptor();
        FileDescriptor out = new FileDescriptor();
        FileDescriptor err = new FileDescriptor();

        String workingPath = (workingDirectory == null)
                ? null
                : workingDirectory.getPath();

        // Ensure onExit() doesn't access the process map before we add our
        // entry.
        synchronized (processReferences) {
            int pid;
            try {
                pid = exec(commands, environment, workingPath, in, out, err);
            } catch (IOException e) {
                IOException wrapper = new IOException("Error running exec()." 
                        + " Commands: " + Arrays.toString(commands)
                        + " Working Directory: " + workingDirectory
                        + " Environment: " + Arrays.toString(environment));
                wrapper.initCause(e);
                throw wrapper;
            }
            ProcessImpl process = new ProcessImpl(pid, in, out, err);
            ProcessReference processReference
                    = new ProcessReference(process, referenceQueue);
            processReferences.put(pid, processReference);

            /*
             * This will wake up the child monitor thread in case there
             * weren't previously any children to wait on.
             */
            processReferences.notifyAll();

            return process;
        }
    
static java.lang.ProcessManagergetInstance()
Gets the process manager.


         
       
        return instance;
    
private static native voidkill(int pid)
Kills the process with the given ID.

parm
pid ID of process to kill

voidonExit(int pid, int exitValue)
Called by {@link #watchChildren()} when a child process exits.

param
pid ID of process that exited
param
exitValue value the process returned upon exit

        ProcessReference processReference = null;

        synchronized (processReferences) {
            cleanUp();
            if (pid >= 0) {
                processReference = processReferences.remove(pid);
            } else if (exitValue == WAIT_STATUS_NO_CHILDREN) {
                if (processReferences.isEmpty()) {
                    /*
                     * There are no eligible children; wait for one to be
                     * added. The wait() will return due to the
                     * notifyAll() call below.
                     */
                    try {
                        processReferences.wait();
                    } catch (InterruptedException ex) {
                        // This should never happen.
                        throw new AssertionError("unexpected interrupt");
                    }
                } else {
                    /*
                     * A new child was spawned just before we entered
                     * the synchronized block. We can just fall through
                     * without doing anything special and land back in
                     * the native wait().
                     */
                }
            } else {
                // Something weird is happening; abort!
                throw new AssertionError("unexpected wait() behavior");
            }
        }

        if (processReference != null) {
            ProcessImpl process = processReference.get();
            if (process != null) {
                process.setExitValue(exitValue);
            }
        }
    
static native voidstaticInitialize()
Initializes native static state.

native voidwatchChildren()
Listens for signals from processes and calls back to {@link #onExit(int,int)}.