public int exec() {
    try {
      executing = true;
      ProcessBuilder pb = new ProcessBuilder(commandArgs);
      if (pwd != null) pb.directory(new File(pwd));

      if (debug) {
        Gpr.debug("PWD: " + pwd);
        for (String arg : commandArgs) Gpr.debug("ARGS: " + arg);
      }

      pr = pb.start();

      // ---
      // Prepare & start stdout/sdterr reader processes
      // ---
      stdErrGobbler = new StreamGobbler(pr.getErrorStream(), true); // StdErr
      stdOutGobbler = new StreamGobbler(pr.getInputStream(), false); // StdOut

      // Quiet? => Do not show
      if (quietStderr) stdErrGobbler.setQuietMode();
      if (quietStdout) stdOutGobbler.setQuietMode();

      // Keep a copy in memory?
      stdErrGobbler.setSaveLinesInMemory(saveStd);
      stdOutGobbler.setSaveLinesInMemory(saveStd);

      // Binary?
      stdErrGobbler.setBinary(binaryStderr);
      stdOutGobbler.setBinary(binaryStdout);

      // Redirect?
      if (redirectStderr != null) stdErrGobbler.setRedirectTo(redirectStderr);
      if (redirectStdout != null) stdOutGobbler.setRedirectTo(redirectStdout);

      // Filter stdout
      stdOutGobbler.setLineFilter(stdOutFilter);

      // Set this object as the progress monitor
      stdErrGobbler.setProgress(this);
      stdOutGobbler.setProgress(this);

      // Start gobblers
      stdErrGobbler.start();
      stdOutGobbler.start();

      // Assign StdIn
      stdin = pr.getOutputStream();

      // ---
      // Start process & wait until completion
      // ---
      started = true;

      // Wait for the process to finish and store exit value
      exitValue = pr.waitFor();

      // Wait for gobblers to finish processing the remaining of STDIN & STDERR
      while (stdOutGobbler.isRunning() || stdErrGobbler.isRunning()) {
        Thread.sleep(100);
      }

      if (debug && (exitValue != 0)) Gpr.debug("Exit value: " + exitValue);
    } catch (Exception e) {
      error = e.getMessage();
      exitValue = -1;
      if (showExceptions) e.printStackTrace();
    } finally {
      // We are done. Either process finished or an exception was raised.
      started = true;
      executing = false;
      if (objetcToNotify != null) {
        synchronized (objetcToNotify) {
          objetcToNotify.notify();
        }
      }
    }

    return exitValue;
  }