How to gracefully close a Java application that terminates as a result of closing the command line from which it was run?

There is an answer to the Best way to gracefully close a Java command line program . The shutdown hook performs the task when the program was interrupted by pressing Ctrl + C.

My question is: how to gracefully exit if the command line itself is closed while the Java program is running? I tested with a stub, but in this case it did not work. I can’t find out what is happening with the virtual machine in this scenario. Is the process and all its threads instantly killed? What signal displays the command line?

So how can this particular problem be solved?

EDIT: The problem is with the Windows environment.

+5
source share
3 answers

Logically, SIGHUP (terminal hang) should be raised.

Actually, I just checked my assumption with a simple shell script. Yes, when the user closes the terminal emulator in which the application was launched (and from which it was not disconnected), the application receives SIGHUP. Therefore, configure the SIGHUP handler and respond accordingly. The usual behavior is to terminate the application, but your intentions may be different.

In addition, if your Java application performs any STDIN / STDOUT operations, it must be closed or at least re-coded upon receipt of the HUP, since attempting to read / write from a non-existing terminal will result in SIGPIPE and / or program block.

For Windows, note Closing the Windows terminal at startup

+2
source

Change for Windows environment:

I don't have much experience in the Windows environment, but if you want your application to continue to work, it usually deploys as a Windows service (this looks like a daemon on Linux). Usually you start / stop / restart the service through a utility that lists all the services (I think you get to it through the control panel → “Administration” → “Services.” I would suggest that issuing a “stop” with this tool signals about graceful shutdown. And if you kill the service through the task manager, it will not be an elegant shutdown.


Is it a Linux or Windows based system? On Linux, if you run the program in the background (and exit the shell with the "exit" command), it will continue. You can place your application in the background by adding at the end. In addition, many applications / services run in the background. If you run the Tomcat startup script using the startup.sh command, it will continue to run in the background, even when you exit the terminal from which you started it. In windows, too, the concept should be similar.

In terms of closing the application, you use the kill command on Linux systems. kill in the process sends a SIGTERM signal to it. Applications can implement code to intercept SIGTERM and disable properly when SIGTERM is detected. If the application does not handle SIGTERM gracefully, it will not respond to SIGTERM / kill. In this case, you need to explicitly tell it SIGKILL (kill -9) to kill it forcibly. In this case, a graceful shutdown is not possible.

0
source

In Java, there is a special Runtime method for this: addShutdownHook .

This allows you to initialize the thread that the JVM will attempt to start immediately before stopping. This is the place to put any cleanup you want to perform, even if you close the closing parent window of Ctrl-C. Extract from javadoc: The disconnect hook is just an initialized, but unexpanded stream. When the virtual machine starts its shutdown sequence, it will start all registered shutdown hooks in some unspecified order and allow them to start at the same time. When all hooks are finished, it will start all uninvited finalizers if output finalization is enabled. Finally, the virtual machine will stop.

The shutdown hook is a call, even if the program ends normally. In this case, clean remove the registered hook before exiting using removeShutdownHook (another method from Runtime )

EDIT:

In the case of the Windows environment, there are no real signals, but special callbacks when the system is turned off. AFAIK, the system hook is correctly called in this case, but I admit that I have never tested this. On Windows, processes can be requested to terminate in two ways:

  • The PostQuitMessage function sends a WM_QUIT message to the event loop - usually the process should exit, but it can do the cleanup (equivalent to Unix SIG_TERM)
  • TerminateProcess immediately stops the process and all its threads (equivalent to Unix SIG_KILL)

Console processes can use the ConsoleControlHandler, which can intercept the events of Ctrl-C, Ctrl-Break, or Ctrl-Close. The first two are generated using the keyboard, the last is generated when the user closes the console. But typically, the Oracle JVM should use the hook mechanism when it receives the Ctrl-Close event, which is handled in the same way as SIGTERM.

0
source

Source: https://habr.com/ru/post/1207785/


All Articles