Steve
Steve Luke wrote:The StreamGobbler uses while(br.ready()) to perform the 'get data from stream' loop. This is not going to work. The br.ready() returns true when there is data in the buffer to be read. When the BufferedReader first starts and before anything is sent to it, the br.ready() will return false - indicating your StreamGobbler should shutdown before it ever started. You can't rely on that. In fact, you can't really rely on anything directly related to the BufferReader to tell you when you need to shutdown.
B Mayes wrote:
Steve Luke wrote:The StreamGobbler uses while(br.ready()) to perform the 'get data from stream' loop. This is not going to work. The br.ready() returns true when there is data in the buffer to be read. When the BufferedReader first starts and before anything is sent to it, the br.ready() will return false - indicating your StreamGobbler should shutdown before it ever started. You can't rely on that. In fact, you can't really rely on anything directly related to the BufferReader to tell you when you need to shutdown.
Man if that is true then the now-classic article "When Runtime.exec() won't" is completely bogus, and thus lots of people should be hosed by this. I'm sure you have read it but here is link for those who haven't:
http://www.javaworld.com/jw-12-2000/jw-1229-traps.html
I think their example is flawed in that it doesn't join the gobbler threads...
but I see what you're saying. It's possible those threads could get scheduled and started prior to the "main" thread executing.
So even though you call join, if those threads read the input stream before any data was written there, they would simply exit and calling join is quite ineffective at that point.
Thanks for the replies...I'll take a look and try some things out tomorrow if I get the chance.
Steve
Steve Luke wrote:
I wouldn't say it is bogus. First, he doesn't use br.ready() he uses br.readLine() != null. That works as long as you assume the gobblers should run until the process kills the streams. That is probably pretty safe, but a forced stop puts it under more control, in my opinion. And lets you close the streams on your end when you are done with them. I personally think a forced stop is cleaner, but but I don't fault the sample code because
1) it is an article with example code, not attempting to be production quality
2) I have never measured or experienced a problem with waiting for the process to close its streams, it just feels wrong to me.
Steve Luke wrote:
There is no real need to join the gobbler threads. Do you really need to block until the gobblers are done? Isn't knowing the process is done good enough? Especially if you can tell the gobbler to end.
Steve Luke wrote:
No, they can't run before main, because main thread creates the gobbler threads, so there is a happens-before relationship between code executed in the main thread (prior to start() being called) and code in the worker thread. But the gobbler threads can easily reach the br.ready() check before the process has put data in the streams.
Steve
Steve Luke wrote:That's great it is working, thanks for the feedback :-)
Steve
Steve Luke wrote:Have you checked the error stream output and the return value from the called application to see if the error was internal and not a problem with you Java code?
$ java SSCCE
Counted 30 time(s) where the output was empty
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
[0,,]
Valid calls look like this: [0,x86_64
,]
Steve
Steve Luke wrote:Hmm... So the returned text you expect is pretty minimal. It could be that the output buffer Windows uses is not being flushed before you call the stop() method because it never gets filled.
Steve Luke wrote:
So this could be a situation where my preference to control the stop versus letting the process die (and join the gobblers) is not good.
$ for i in $(seq 1 100)
> do
> java SSCCE
> done
Counted 0 time(s) where the output was empty
Counted 0 time(s) where the output was empty
Counted 0 time(s) where the output was empty
Counted 0 time(s) where the output was empty
Counted 0 time(s) where the output was empty
...
Steve Luke wrote:
/* completely untested example... maybe add a timeout, and better return or error handling or something... */
Thank you my well lotioned goddess! Here, have my favorite tiny ad!
Smokeless wood heat with a rocket mass heater
https://woodheat.net
|