Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you gracefully exit a Process in Java?

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)?

like image 686
RunasSudo Avatar asked Jul 24 '26 12:07

RunasSudo


1 Answers

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();
    }
  }
}
like image 102
GETah Avatar answered Jul 26 '26 01:07

GETah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!