tags:

views:

1331

answers:

2

I am trying to call cleartool from an java application, but cleartool hangs even for a simple "-version" argument. Running cleardiff instead of cleartool works fine, so apparently there is something specific with the cleartool program (which I assume is related to its interactive capabilities).

The following program

import java.io.*;
import java.util.*;

public class ExecTesting extends Thread {

    private List<String> command = new ArrayList<String>();

    public ExecTesting (List<String> command) {
     super();
     this.command = command;
    }

    private void print(String s) {
     System.out.println(s);
    }

    @Override
    public void run() {
     Process process;
     OutputStream stdin;
     InputStream stdout;
     InputStream stderr;
     String line;

     try {
      String commandString = joinList(command, " ");
      print("Executing: " + commandString);

      // runtime.exec has several issues (http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1)
      // better to use ProcessBuilder (http://java.sun.com/developer/JDCTechTips/2005/tt0727.html#2)
      //process = Runtime.getRuntime().exec(commandString);
      process = new ProcessBuilder(command).start();
      // it fails in both cases though

      stdin  = process.getOutputStream();
      stdout = process.getInputStream();
      stderr = process.getErrorStream();

      BufferedReader bufferedStderr = new BufferedReader(new InputStreamReader(stderr));
      while ((line = bufferedStderr.readLine()) != null) {
       print("stderr: " + line);
      }
      bufferedStderr.close();

      BufferedReader bufferedStdout = new BufferedReader(new InputStreamReader(stdout));
      while ((line = bufferedStdout.readLine()) != null) {
       print("stdout: " + line);
      }
      bufferedStdout.close();

      stdin.close();
      stdout.close();
      stderr.close();

      process.waitFor();
      print("Execution finished, exit code " + process.exitValue());
      process.destroy();
     } catch (IOException e) {
      print("IOException: " +e.getStackTrace());
     } catch (InterruptedException e) {
      print("InterruptedException: " + e.getStackTrace());
     }

    }

    /* assumes a list with at least one element */
    private static String joinList(List<String> list, String glue) {
     Iterator<String> i = list.iterator();
     String ret = i.next();
     while (i.hasNext()) {
      ret += glue + i.next();
     }
     return ret;
    }

    public static void main(String[] args) {
     ArrayList<String> cmd1 = new ArrayList<String>();
     cmd1.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleardiff.exe");
     cmd1.add("-version");
     ExecTesting et1 = new ExecTesting(cmd1);
     et1.start();

     ArrayList<String> cmd2 = new ArrayList<String>();
     //cmd2.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleardiff.exe");
     cmd2.add("c:\\Program Files\\Rational\\ClearCase\\bin\\cleartool.exe");
     cmd2.add("-version");
     ExecTesting et2 = new ExecTesting(cmd2);
     et2.start();

     et1 = new ExecTesting(cmd1);
     et1.start();
    }
}

gives the following output

Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleartool.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
stdout: cleardiff                         2003.06.10+ (Tue Jul 13 14:02:05  2004)
Execution finished, exit code 0

hanging on the execution of the cleartool command. If instead cmd2 is changed to cleardiff the output is as expected

Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
Executing: [c:\Program Files\Rational\ClearCase\bin\cleardiff.exe, -version]
stdout: cleardiff                         2003.06.10+ (Tue Jul 13 14:02:05  2004)
Execution finished, exit code 0
stdout: cleardiff                         2003.06.10+ (Tue Jul 13 14:02:05  2004)
Execution finished, exit code 0
stdout: cleardiff                         2003.06.10+ (Tue Jul 13 14:02:05  2004)
Execution finished, exit code 0

Question: Does anyone know why cleartool is hanging and how to fix?

+1  A: 

You should consume the stdout and stderr in separate threads, otherwise you will experience blocking behaviour.

I suspect that's what's happening in this instance (and that it's unrelated to cleartool/cleardiff other than they're outputting stdout/err). See this answer for more information.

Brian Agnew
+2  A: 

It seems you close the I/O streams BEFORE you start to wait for the termination. Also you read the stderr and stdout sequentially. However, the read to stderr blocks as there are no errors printed by the application and you don't move to the phase where you read the stdout. This deadlocks.

You could join the stderr and stdout via ProcessBuilder.redirectErrorStream() and then you need only to read stdout.

Your sample works in some cases because when you are blocked on the stderr, the application response on the stdout doesn't hit the size of the communication buffer. When the application quits, the stderr loop exits and the loop for stdout is able to retieve the contents of that buffer.

kd304