How do you handle clean up when the program receives a kill signal?
For instance, there is an application I connect to that wants any third party app (my app) to send a finish
command when logging out. What is the best say to send that finish
command when my app has been destroyed with a kill -9
?
edit 1: kill -9 cannot be captured. Thank you guys for correcting me.
edit 2: I guess this case would be when the one calls just kill which is the same as ctrl-c
I would expect that the JVM gracefully interrupts (
thread.interrupt()
) all the running threads created by the application, at least for signalsSIGINT (kill -2)
andSIGTERM (kill -15)
.This way, the signal will be forwarded to them, allowing a gracefully thread cancellation and resource finalization in the standard ways.
But this is not the case (at least in my JVM implementation:
Java(TM) SE Runtime Environment (build 1.8.0_25-b17), Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
.As other users commented, the usage of shutdown hooks seems mandatory.
So, how do I would handle it?
Well first, I do not care about it in all programs, only in those where I want to keep track of user cancellations and unexpected ends. For example, imagine that your java program is a process managed by other. You may want to differentiate whether it has been terminated gracefully (
SIGTERM
from the manager process) or a shutdown has occurred (in order to relaunch automatically the job on startup).As a basis, I always make my long-running threads periodically aware of interrupted status and throw an
InterruptedException
if they interrupted. This enables execution finalization in way controlled by the developer (also producing the same outcome as standard blocking operations). Then, at the top level of the thread stack,InterruptedException
is captured and appropriate clean-up performed. These threads are coded to known how to respond to an interruption request. High cohesion design.So, in these cases, I add a shutdown hook, that does what I think the JVM should do by default: interrupt all the non-daemon threads created by my application that are still running:
Complete test application at github: https://github.com/idelvall/kill-test
You can use
Runtime.getRuntime().addShutdownHook(...)
, but you cannot be guaranteed that it will be called in any case.There is one way to react to a kill -9: that is to have a separate process that monitors the process being killed and cleans up after it if necessary. This would probably involve IPC and would be quite a bit of work, and you can still override it by killing both processes at the same time. I assume it will not be worth the trouble in most cases.
Whoever kills a process with -9 should theoretically know what he/she is doing and that it may leave things in an inconsistent state.
There are ways to handle your own signals in certain JVMs -- see this article about the HotSpot JVM for example.
By using the Sun internal
sun.misc.Signal.handle(Signal, SignalHandler)
method call you are also able to register a signal handler, but probably not for signals likeINT
orTERM
as they are used by the JVM.To be able to handle any signal you would have to jump out of the JVM and into Operating System territory.
What I generally do to (for instance) detect abnormal termination is to launch my JVM inside a Perl script, but have the script wait for the JVM using the
waitpid
system call.I am then informed whenever the JVM exits, and why it exited, and can take the necessary action.
The way to handle this for anything other than
kill -9
would be to register a shutdown hook. If you can use (SIGTERM)kill -15
the shutdown hook will work. (SIGINT)kill -2
DOES cause the program to gracefully exit and run the shutdown hooks.I tried the following test program on OSX 10.6.3 and on
kill -9
it did NOT run the shutdown hook, didn't think it would. On akill -15
it DOES run the shutdown hook every time.There isn't any way to really gracefully handle a
kill -9
in any program.The only real option to handle a
kill -9
is to have another watcher program watch for your main program to go away or use a wrapper script. You could do with this with a shell script that polled theps
command looking for your program in the list and act accordingly when it disappeared.