public String run() throws IOException {
    Process process = new ProcessBuilder(mCommand).redirectErrorStream(true).start();

    BufferedReader inReader =
            new BufferedReader(new InputStreamReader(process.getInputStream(),
                    Charset.defaultCharset()));

    try {
      // read the output of the command
      StringBuilder output = new StringBuilder();
      String line = inReader.readLine();
      while (line != null) {
        output.append(line);
        output.append("\n");
        line = inReader.readLine();
      }
      // wait for the process to finish and check the exit code
      int exitCode = process.waitFor();
      if (exitCode != 0) {
        throw new ShellUtils.ExitCodeException(exitCode, output.toString());
      }
      return output.toString();
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      throw new IOException(e);
    } finally {
      // close the input stream
      try {
        // JDK 7 tries to automatically drain the input streams for us
        // when the process exits, but since close is not synchronized,
        // it creates a race if we close the stream first and the same
        // fd is recycled. the stream draining thread will attempt to
        // drain that fd!! it may block, OOM, or cause bizarre behavior
        // see: https://bugs.openjdk.java.net/browse/JDK-8024521
        // issue is fixed in build 7u60
        InputStream stdout = process.getInputStream();
        synchronized (stdout) {
          inReader.close();
        }
      } catch (IOException e) {
        LOG.warn(String.format("Error while closing the input stream of process %s: %s",
                process, e.getMessage()));
      }
      process.destroy();
    }
  }
@Test
  public void execCommandFail() throws Exception {
    mExceptionRule.expect(ShellUtils.ExitCodeException.class);
    // run a command that guarantees to fail
    String[] cmd = new String[]{"bash", "-c", "false"};
    String result = new ShellCommand(cmd).run();
    assertEquals("false\n", result);
  }