Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exiting an application gracefully?

I have an application with a well defined Try/Catch/Finally chain that exits and executes the finally block just fine under normal conditions, however when someone prematurely hits the red X in the GUI, the program fully exists (code = 0) and the main thread's finally block isn't called.

In fact, I do want the program to exit upon a click of the red-X, but what I do not want is a skipping of the finally{} block! I sort of put in the most important part of the finally block manually in the GUI but I really do not want to do it this way since I want the GUI decoupled from the actual program:

class GUI { // ...
...
mainFrame.addWindowListener(new WindowAdapter() {
  public void windowClosing(WindowEvent evt) {
    try {
      processObject.getIndicatorFileStream().close();
    } catch (Exception ignore) {}
    System.exit(0);
  }
});
...
}

But I'd prefer to just have a call like this:

mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

And make sure that all the finally{} blocks get called from each thread after the Exit.

I know this is actually expected. If the application is closed from a separate thread (say the GUI thread) then the main thread will just stop in its tracks.

In short -- how do I ensure that a System.exit(0) or a JFrame.EXIT_ON_CLOSE will still cause each thread's finally block to execute?

like image 866
E.S. Avatar asked Jul 22 '13 16:07

E.S.


People also ask

What is meant by graceful exit?

A graceful exit (or graceful handling) is a simple programming idiom wherein a program detects a serious error condition and "exits gracefully" in a controlled manner as a result. Often the program prints a descriptive error message to a terminal or log as part of the graceful exit.

How to exit Java program gracefully?

exit() in a Java application would be a graceful exit. If the program crashes or is force killed, exit or shutdown hooks would not be fired.

How do I stop Go app?

To exit an application in Go, use the os. Exit() function from the os package. It causes the program to terminate immediately.


2 Answers

If you have no other design change choices then what you may need is a JVM shutdown hook, which can be added to run a piece of code when System.exit is called.

Shutdown Hooks are a special construct that allow developers to plug in a piece of code to be executed when the JVM is shutting down. This comes in handy in cases where we need to do special clean up operations in case the VM is shutting down.

You can add a shutdown hook as mentioned here:

Runtime.getRuntime().addShutdownHook(Thread)

Read more about shutdown hooks here:

http://java.dzone.com/articles/know-jvm-series-2-shutdown

Word of Caution:

We must keep in mind is that it is not guaranteed that shutdown hooks will always run. If the JVM crashes due to some internal error, then it might crash down without having a chance to execute a single instruction. Also, if the O/S gives a SIGKILL (http://en.wikipedia.org/wiki/SIGKILL) signal (kill -9 in Unix/Linux) or TerminateProcess (Windows), then the application is required to terminate immediately without doing even waiting for any cleanup activities. In addition to the above, it is also possible to terminate the JVM without allowing the shutdown hooks to run by calling Runime.halt() method.

like image 117
Juned Ahsan Avatar answered Oct 12 '22 02:10

Juned Ahsan


If you happen to have such threads which can legally be stopped at any time, at any point at all within their loop, at any point within any method which they invoke, and may I warn you that it is very unlikely that you do, then you can stop all of them upon program exit. This will result in an exception being thrown in each thread, and the finally blocks will execute.

However, the proper way to achieve your goal and have GUI decoupled from the program logic, is to issue a single "exit" signal from the GUI, which will trigger all the application cleanup, which is written in an entirely different class. If you have running threads, then implement the interrupt mechanism in each of them.

There are many ways to achieve the exit signaling. For example, your business code could register a GUI listener for a special event, which would trigger the cleanup. You could also have a thread which doesn't do anything else but await on a CountDownLatch which would be countDown from the GUI.

Please, do not at any cost use a shutdown hook. This is the dirtiest mechanism imaginable, and it is there only as a last resort, when all regular cleanup procedures fail. It is never to be used as a part of the regular shutdown routine.

In summary, there is no royal way to clean application shutdown. You must implement specific mechanisms for each specific concern.

like image 25
Marko Topolnik Avatar answered Oct 12 '22 03:10

Marko Topolnik