views:

872

answers:

2

I'm using Java's ProcessBuilder class to run an external process. The process should not terminate before the Java program does; it must stay alive in command/response mode.

I know that the process streams may easily 'jam' if neglected, so I've done the following: The program reads the process's combined output and error streams in a "reader" thread, and uses a "writer" thread to manage the commands. The reader thread does blocking character reads from process output, buffers them up into Strings and dispatches the results. The writer thread writes complete "command" lines via a PrintWriter; it uses a queue to ensure that no two command writes are "too close together" (currently 100ms), and that no new command gets written before the output of the previous command is complete. I also call flush() and checkError() after every println().

This scheme works fine for a few seconds or minutes, then the reader thread hangs on the blocking read(). No errors, no exceptions thrown, no more process output. Thereafter nothing will revive the external process (short of restarting it). (BTW this happens on both Linux and Windows.)

I've looked at the code and test-cases in Jakarta Commons Exec and in Plexus Utils http://plexus.codehaus.org/plexus-utils/ but (a) neither gives an example of using a long-lived Process and (b) neither appears to be doing anything basically different from what I've described.

Does anyone have a clue what's happening here please? Thanks!

+1  A: 

Do you also have a thread managing stderr? You only mention the two streams.

Benj
I call processBuilder.redirectErrorStream(true); before processBuilder.start(). SO there should only be one combined output stream.
ProfCalculus
Are you using a debugger? If so does it support showing which threads own/want mutexes like the eclipse one does? Sounds like it could be a deadlock.
Benj
Yes I've debugged it in Eclipse, but the main app keeps running quite happily - it just can't do anything useful until the reader returns some data.
ProfCalculus
A: 

Just a guess, but have you tried un-combining the error and output streams?

flicken
No I haven't and I'll try that next, but I'm not too optimistic. If redirectErrorStream doesn't work, that's a bug in ProcessBuilder. And I do actually see some stderr output on my combined stream before it dies.
ProfCalculus
OK I've tried splitting the streams, and the error stream is handled by its own thread. No change in the stdout behaviour though...
ProfCalculus