Java IO I / O blocks when reading standard output and standard error of an external C program

I posted the same question here a few days ago ( Java reading standard output from an external program using an input stream ), and I found some great tips in solving with a block while reading (while (is.read ())! = -1)), but I still can not solve the problem.

After reading the answers to this similar question,

Reading InputStream input lock (esp, response sent by Guss),

I am starting to believe that a cyclic input stream using is.read ()! = -1 condition does not work if the program is interactive (that is, it accepts several inputs from the user and presents additional outputs on subsequent inputs, and the program exits only when explicit exit command is given). I admit that I don’t know much about multithreading, but I think I need a mechanism to quickly suspend input streams (one for stdout, stderr one) when user input is required, and resume work after input to prevent blocking. The following is my current code that is testing a block on the specified line:

  EGMProcess egm = new EGMProcess (new String [] {directory + "/ egm", "-o",
                 "CasinoA", "-v", "VendorA", "-s", "localhost: 8080 / gls / MessageRobot.action",
                 "-E", "glss_env_cert.pem", "-S", "glss_sig_cert.pem", "-C", "glsc_sig_cert.pem",
                 "-d", "config", "-L", "config / log.txt", "-H", "GLSA-SampleHost"}, new String [] {"PATH = $ {PATH}"}, directory );

egm.execute(); BufferedReader stdout = new BufferedReader(new InputStreamReader(egm.getInputStream())); BufferedReader stderr = new BufferedReader(new InputStreamReader(egm.getErrorStream())); EGMStreamGobbler stdoutprocessor = new EGMStreamGobbler(stdout, egm); EGMStreamGobbler stderrprocessor = new EGMStreamGobbler(stderr, egm); BufferedWriter stdin = new BufferedWriter(new OutputStreamWriter(egm.getOutputStream())); stderrprocessor.run(); //<-- the block occurs here! stdoutprocessor.run(); //EGM/Agent test cases //check bootstrap menu if(!checkSimpleResult("******** EGM Bootstrap Menu **********", egm)) { String stdoutdump = egm.getStdOut(); egm.cleanup(); throw new Exception("can't find '******** EGM Bootstrap Menu **********'" + "in the stdout" + "\nStandard Output Dump:\n" + stdoutdump); } //select bootstrap stdin.write("1".toCharArray()); stdin.flush(); if(!checkSimpleResult("Enter port to receive msgs pushed from server ('0' for no push support)", egm)){ String stdoutdump = egm.getStdOut(); egm.cleanup(); throw new Exception("can't find 'Enter port to receive msgs pushed from server ('0' for no push support)'" + "in the stdout" + "\nStandard Output Dump:\n" + stdoutdump); } 

...

public class EGMStreamGobbler implements Runnable {

private BufferedReader instream; private EGMProcess egm; public EGMStreamGobbler (BufferedReader isr, EGMProcess aEGM) {instream = isr; egm = aEGM; } public void run () {try {int c; while ((c = instream.read ())! = 1) {egm.processStdOutStream ((char) c); }} catch (IOException e) {e.printStackTrace (); }}

}

Sorry for the length of the code, but my questions are:

1) Is there a way to control the input process (stdout, stderr) without using read ()? Or am I just doing it poorly?

2) Is multithreading the right strategy for developing an input process and writing output?

PS: if someone can provide a similar problem with the solution, this will help me a lot!

+4
source share
4 answers

instead

 stderrprocessor.run(); //<-- the block occurs here! stdoutprocessor.run(); 

You need to start the threads:

 Thread errThread = new Thread(stderrprocessor); errThread.setDaemon( true ); errThread.start(); Thread outThread = new Thread(stdoutprocessor); outThread.setDaemon( true ); outThread.start(); 

run() is just the method specified in Runnable . Thread.start() calls run() on Runnable in the new Thread .

+8
source
  • If you just call #run () on runnable, it will not execute in parallel. To run it in parallel, you must create java.lang.Thread, which executes #run () of your Runnable.
  • Regardless of whether the flow depends on both sides of the flow. If the sender does not send any data or the receiver does not receive data, you have a block situation. If the processor needs to do something while the thread is blocked, you need to create a thread (zero) in the processor in order to wait for new data and interrupt the alternative process when new data flows.
+2
source

First you need to read "Thread and Runnable". You do not call Runnable.run () directly, you configure Threads for this and start threads.

But more importantly, having three independent threads implies the need for some careful development. Why 3 threads? You just started, and most importantly.

I assume that the general idea of ​​your application is to wait for any result to appear, interpret it and as a result send a command to the application that you control?

So, your main thread should wait until one of the reader threads says β€œAha!”, Which is interesting, better ask the user what he wants to do. "

In other words, you need a communication mechanism between your readers and your author. This can be implemented using the Java event mechanism. I'm still afraid that I read more.

+1
source

Wasn't it created by nio?

I don't know much about Channels in nio, but this answer may be helpful. It shows how to read a file using nio. May be helpful.

+1
source

All Articles