Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java process.getInputStream() has nothing to read, deadlocks child

I am having an issue with some process wrapping, and it's only occurring in Windows XP. This code works perfectly in Windows 7. I'm really stumped as to why the streams are empty in XP. I've also tried using the String[] version of Process.Exec() and it made no difference.

I am using the following class to read from the process' STDOUT and STDERR (an instance for each stream):


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

public class ThreadedStreamReader extends Thread{
 InputStream in;
 Queue messageQueue;

 public ThreadedStreamReader(InputStream s, Queue q)
 {
  in = s;
  messageQueue = q;
 }

 public void run()
 {
  try
  {
   BufferedReader r = new BufferedReader(new InputStreamReader(in));
   String line = null;
   while((line = r.readLine()) != null)
   {
    synchronized(messageQueue)
    {
     messageQueue.add(line);
    }
   }

  }catch(Exception e)
  {
   System.err.println("Bad things happened while reading from a stream");
  }
 }
}

And I use it here:


Process p = Runtime.getRuntime().exec("test.exe");
Queue&ltString&gt q = new LinkedList&ltString&gt();

ThreadedStreamReader stdout = new ThreadedStreamReader(p.getInputStream(), q);
ThreadedStreamReader stderr = new ThreadedStreamReader(p.getErrorStream(), q);

stdout.start();
stderr.start();

while(true)
{
    while(q.size() > 0)
    {
        System.out.println(q.remove());
    }
}

Anyone have any ideas? Thanks!

Edit: Added synchronization

Edit: Just as an update, the parent stream readers are blocked on their read operation. If I kill the child processes, with the task manager, they read in the null from the closing of the stream.

like image 850
Banana Avatar asked Sep 21 '10 02:09

Banana


3 Answers

You need to use a threadsafe data structure; I don't think LinkedList is threadsafe.

like image 183
Jason S Avatar answered Nov 15 '22 15:11

Jason S


One mistake that strikes me is that LinkedList is not synchronized, but you're trying to write to it in 2 threads.

Another thing to keep in mind is Process.getInputStream() returns the stdout stream of the process, so you should rename the variable currently called stdin to stdout to prevent confusion.

like image 23
oksayt Avatar answered Nov 15 '22 15:11

oksayt


There are known bugs in pre-Vista Windows operating systems where loading DLLs can cause a hang in IO.

e.g. see http://weblogs.java.net/blog/kohsuke/archive/2009/09/28/reading-stdin-may-cause-your-jvm-hang and https://connect.microsoft.com/VisualStudio/feedback/details/94701/loadlibrary-deadlocks-with-a-pipe-read

I'm not sure if this is what you are running in to, but it may be related.

Also, I vaguely recall some issues in getting a valid stdin and stdout from non-console windows applications. If your call to 'test.jar' is using 'javaw' rather than 'java', then this could be the cause of your problem, too.

like image 23
Burleigh Bear Avatar answered Nov 15 '22 14:11

Burleigh Bear