Running haskell executable using Java ProcessBuilder: why does hGetLine only return after closing outputStream?
I am terminating a FM-SBLEX Saldo program in a Java library.
Saldo is written in Haskell and searches the lexicon for strings given to stdin, for example
echo "ord"|./sblex/bin/saldo dicts/saldo.dict
outputs something like the following to stdout
{"ord":{"s_1":{"word":"ord","head":"sanna mina ord","pos":"abm","param":"invar 1:3-3","inhs":[],"id":"sanna_mina_ord..abm.1","p":"abm_i_till_exempel","attr":"3"},...
If I run it with
./sblex/bin/saldo dicts/saldo.dict
it searches every line I typed in the console until I submit an EOF.
In my Java library, I run it with ProcessBuilder and set up a stream to output stdout and stderr to my stdout program, and another stream writes word and newline and then clears the outputStream
On the console, saldo returns results every time I hit return, but in my wrapper, it only returns results for all of my input once when I close the outputStream (see close () commented out in the following code block)
ProcessBuilder pb = new ProcessBuilder(binPath, dictPath);
pb.redirectErrorStream(true);
saldoProcess = pb.start();
new Thread(new Reader(saldoProcess.getInputStream())).start();
new Thread(new Writer(saldoProcess.getOutputStream())).start();
saldoProcess.waitFor();
System.out.println("saldo exited.");
Thread.sleep(2000);
Shutting down Writer:
public void run() {
try {
outputStream.write("ord\n".getBytes());
outputStream.flush();
//outputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Haskell code that reads input
run' :: Language a => a -> (String -> [Tok]) -> (String -> [[String]]) -> AnaType -> Stats -> IO Stats
run' l tokenizer f a st =
do b <- hIsEOF stdin
if b then return st
else do
s <- hGetLine stdin
analyze l a f (tokenizer s) st >>= run' l tokenizer f a
If binPath = "cat" and dictPath = "-" then my java program prints the input after every reset. Any idea why this haskell program only deals with input after closing the output stream?
NB: as the answer shows, there was no hGetLine that didn't return (as I assumed), but output that was buffered because the Haskell implementation I use by default to block the buffer if it is not run from the console.
source to share
Your Haskell program is probably buffering its output. (Buffered line by line when writing to the terminal, buffered when writing to anything else.)
Try adding
hSetBuffering stdout LineBuffering
near the start of the program.
Learn more about buffering in Haskell.
(Edited in response to comment by Daniel Wagner.)
source to share