org.linkedin.util-core/src/main/java/org/linkedin/util/concurrent/ExternalCommand.java
public int waitFor(long timeout) throws InterruptedException, TimeoutException
  {
    if(_process == null)
      throw new IllegalStateException("you must call start first");

    Chronos c = new Chronos();
    _out.join(timeout);
    timeout -= c.tick();
    if (timeout <= 0)
      throw new TimeoutException("Wait timed out");
    _err.join(timeout);
    timeout -= c.tick();
    if (timeout <= 0)
      throw new TimeoutException("Wait timed out");
    
    // there is no timeout in this API, not much we can do here
    // waiting on the other two threads should give us some safety
    return _process.waitFor();
  }
public int waitFor(long timeout) throws InterruptedException, TimeoutException
  {
    if(_process == null)
      throw new IllegalStateException("you must call start first");

    Chronos c = new Chronos();
    _out.join(timeout);
    timeout -= c.tick();
    if (timeout <= 0)
      throw new TimeoutException("Wait timed out");
    _err.join(timeout);
    timeout -= c.tick();
    if (timeout <= 0)
      throw new TimeoutException("Wait timed out");
    
    // there is no timeout in this API, not much we can do here
    // waiting on the other two threads should give us some safety
    return _process.waitFor();
  }
Properly waits until everything is complete: joins on the thread that
reads the output, joins on the thread that reads the error and finally
wait for the process to be finished.
If the process has not completed before the timeout, throws a
{@link TimeoutException}
@return the status code of the process.

@throws TimeoutException
@throws InterruptedException