3

I am trying to make a Java program which will run several other unrelated Java programs, specifically a Minecraft server. Currently, I am trying to work out how to end a java.lang.Process gracefully.

This is the code for my spawner program: http://dl.dropbox.com/u/26746878/SpawnerSource/Main.java.txt

And this is the code for the program which is spawned: http://dl.dropbox.com/u/26746878/SpawnerSource/Tester.java.txt

What I do is run my spawner program. Then, after a few seconds, I terminate it with Ctrl-C. What I want to see is my program output 'Shutting Down' followed by 'Ending'. I also want to see a file 'test.txt'. What I actually see is only 'Shutting Down', with no 'Ending' nor 'test.txt'

I believe the problem is that Process.destroy() is forcefully ending the process without letting the shutdown hooks run.

Is there an alternative to Process.destroy() which will exit the process gracefully (ie: as if I had pressed Ctrl-C)?

RunasSudo
  • 483
  • 2
  • 4
  • 13
  • Is there a particular justification for using Java to perform this task, over say a shell script/batch file? – Mark Peters Nov 27 '11 at 03:34
  • @MarkPeters I want to eventually have this program listen on a particular port, and have a PHP script connect to it, and have the program execute commands on the spawned processes, and I would much rather use Java for this than anything else. – RunasSudo Nov 27 '11 at 03:36
  • possible duplicate of [How to stop java process gracefully?](http://stackoverflow.com/questions/191215/how-to-stop-java-process-gracefully) – KV Prajapati Nov 27 '11 at 03:40
  • 1
    So, because you're comfortable with Java, regardless of whether it's the right tool for the job? Java doesn't have very rich process management support. – Mark Peters Nov 27 '11 at 03:41
  • 1
    @AVD: completely different. This question is about shutting down external processes from within Java, that question was about shutting down gracefully when sent a signal from an external process. – Mark Peters Nov 27 '11 at 03:42
  • @MarkPeters Well, I want to know if this thing would be easy, hard, extremely hard, or impossible. Because if it's any of the first 3, I'll take it. Also, how would I get a shell script/batch file to listen on a port? – RunasSudo Nov 27 '11 at 03:46
  • @pokepal101: Well if you need to listen on a port, then depending on what you need to do I'm not sure I would recommend a shell script. But a richer scripting language like Perl or Python which has more native bindings might work well. It's hard to send signals to Java without going through a native layer like JNI/JNA. This simply doesn't play well to Java's strengths because process management is OS-dependent, and so Java won't give you great support (at least out of the box). – Mark Peters Nov 27 '11 at 03:50

2 Answers2

2

You may want to look into Remote Method Invocation, and have your spawner process ask the child processes to shut themselves down instead of having the spawner process kill the child processes itself.

Kane
  • 4,047
  • 2
  • 24
  • 33
2

You should never destroy a working process as it might get the whole OS into an unstable state (believe me, this caused us 2 hours downtime and cost 10000$ to my company :( ) What you should do instead is as @Kane mentioned, send a shutdown request to all your child processes and wait until they are all finished (every child process sends an RMI notification back to the main process right before gracefully exiting)

class ParentProcess{
  Map<int, CountDownLatch> finishSignals = new ConcurrentHashMap<int, CountDownLatch>();
  public void startProcess(){
    // Start child process
    // get its ID
    // and create a count down latch for it
    finishSignals.add(processId, new CountDownLatch(1));
  }
  public void shutDownProcess(processId){
    // Send an RMI request to process ID to shutdown
  }
  // RMI request sent from child process before stopping
  public void processFinishedNotification(processId){
    finishSignals[processId].countDown()
  }
  public void waitForChildsToFinish(){
    // This for loop will block until all child processes have sent a finish notification
    for(CountDownLatch childFinishSignal : finishSignals){
      childFinishSignal.await();
    }
  }
}
GETah
  • 20,922
  • 7
  • 61
  • 103