code: public final int joinWithTimeout(final long timeout, final TimeUnit unit,
              final TaskListener listener) throws IOException, InterruptedException {
          final CountDownLatch latch = new CountDownLatch(1);
          try {
              executor.submit(new Runnable() {
                  public void run() {
                      try {
                          if (!latch.await(timeout, unit)) {
                              listener.error("Timeout after " + timeout + " " +
                                      unit.toString().toLowerCase(Locale.ENGLISH));
                              kill();
                          }
                      } catch (InterruptedException | IOException | RuntimeException x) {
                          Functions.printStackTrace(x, listener.error("Failed to join a process"));
                      }
                  }
              });
              return join();
          } finally {
              latch.countDown();
          }
      }
docs: Like {@link #join} but can be given a maximum time to wait.
  @param timeout number of time units
  @param unit unit of time
  @param listener place to send messages if there are problems, incl. timeout
  @return exit code from the process
  @throws IOException for the same reasons as {@link #join}
  @throws InterruptedException for the same reasons as {@link #join}
  @since 1.363