• Post Reply Bookmark Topic Watch Topic
  • New Topic

spawning a process  RSS feed

 
B Mayes
Ranch Hand
Posts: 47
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi all,

This is really my first attempt to use the Process class in Java. I'm running into some issues and just want to be sure I know why. So to start, here is a very simple BASH script to determine whether or not the input number is even or odd:




Now here is a very simply Java program to invoke that code:




The problem I'm running into is that the program often outputs nothing, but when I run it through my debugger it outputs something every time. I eventually got it to output sometimes when running normally so I think that the issue is really timing. I have the following questions:

1. Is the program outputting nothing because the call to exec() simply spawns the new process but does not wait for it to finish before moving on?
2. In order to always force the program to output something I guess I want to call p.waitFor() ?
3. I see that p.getInputStream() and p.getErrorStream() can block if the size of the output exceeds the buffer size. Thus, it is best to place these calls in separate threads...ok fine. But will calling p.waitFor() ever block (assuming the process being called always terminates)?


I believe the answers to the above questions are yes, yes, and no. I'm just trying to understand things a bit better here. It seems like you cannot rely on the process to be terminated without waitFor() so the best thing to do is:

- Call the process to be run with exec()
- Spawn thread(s) to read stdout/stderr
- call waitFor()

At this point you can be certain that the process completed and that you read all of the output without blocking.

4. The only problem is that I cannot see how to get the output of the command inside of the calling thread. Instead, the output is only available inside of the spawned thread (which we created to prevent blocking). I suppose I could add a public method to append whatever the thread reads to an object in the calling class, but that's a bit cumbersome. Anyone have any other ideas? In the grand scheme of things it may not matter anyway...I'm just going to have my thread throw an exception if it encounters certain strings but I'm just curious. Thanks!
 
Campbell Ritchie
Marshal
Posts: 56562
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Don't go anywhere near Runtime.exec() or Process until you have read the classic article by Michael Daconta, When Runtime.exec() won't. It might be over ten years old, but it is still relevant. It is a little easier if you use a ProcessBuilder.

I don't think this is a "beginning" question, so shall move it.
 
B Mayes
Ranch Hand
Posts: 47
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, but I have actually already read that article. When I first ran some google searches I stumbled upon that pretty quickly, but I didn't think that it directly answered any of my questions so I'm simply extrapolating answers from my own experience as well as what that article suggests. Furthermore, using ProcessBuilder doesn't seem to do any better. In fact, I cannot get it to produce any output at all, even if I throw in a call to Thread.sleep() for several seconds.

The new code is as follows:

 
Campbell Ritchie
Marshal
Posts: 56562
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Aren't you supposed to empty the error stream, too? You can do that by merging the two streams in the ProcessBulider class.
 
B Mayes
Ranch Hand
Posts: 47
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I didn't know that flushing stderr was required -- I thought it was more of an optional thing. However, after flushing stderr I do see some error output so that might explain why it's not printing anything. I'll play around with things a bit more and report back.
 
B Mayes
Ranch Hand
Posts: 47
Android Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
D'oh. Silly me I shouldn't have been using the -c option to bash. As soon as I removed that it works perfectly (assuming waitFor() is used). Here is the final code:




So that's cool, but I still haven't ever received confirmation on my first three questions:

1. Is the program outputting nothing because the call to exec() simply spawns the new process but does not wait for it to finish before moving on?
2. In order to always force the program to output something I guess I want to call p.waitFor() ?
3. I see that p.getInputStream() and p.getErrorStream() can block if the size of the output exceeds the buffer size. Thus, it is best to place these calls in separate threads...ok fine. But will calling p.waitFor() ever block (assuming the process being called always terminates)?


Again, I believe the answers are yes, yes, and no but it would be great if someone with more expertise in this area could confirm.
 
Consider Paul's rocket mass heater.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!