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
It is impossible for any program, in any language, to handle a SIGKILL. This is so it is always possible to terminate a program, even if the program is buggy or malicious. But SIGKILL is not the only means for terminating a program. The other is to use a SIGTERM. Programs can handle that signal. The program should handle the signal by doing a controlled, but rapid, shutdown. When a computer shuts down, the final stage of the shutdown process sends every remaining process a SIGTERM, gives those processes a few seconds grace, then sends them a SIGKILL.
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.
Registers a new virtual-machine shutdown hook.
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
I tried the following test program on OSX 10.6.3 and on kill -9 it did NOT run the shutdown hook, as expected. On a kill -15 it DOES run the shutdown hook every time.
public class TestShutdownHook
{
public static void main(String[] args) throws InterruptedException
{
Runtime.getRuntime().addShutdownHook(new Thread()
{
#Override
public void run()
{
System.out.println("Shutdown hook ran!");
}
});
while (true)
{
Thread.sleep(1000);
}
}
}
There isn't any way to really gracefully handle a kill -9 in any program.
In rare circumstances the virtual
machine may abort, that is, stop
running without shutting down cleanly.
This occurs when the virtual machine
is terminated externally, for example
with the SIGKILL signal on Unix or the
TerminateProcess call on Microsoft
Windows.
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 the ps command looking for your program in the list and act accordingly when it disappeared.
#!/usr/bin/env bash
java TestShutdownHook
wait
# notify your other app that you quit
echo "TestShutdownHook quit"
I would expect that the JVM gracefully interrupts (thread.interrupt()) all the running threads created by the application, at least for signals SIGINT (kill -2) and SIGTERM (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:
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Interrupting threads");
Set<Thread> runningThreads = Thread.getAllStackTraces().keySet();
for (Thread th : runningThreads) {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.getClass().getName().startsWith("org.brutusin")) {
System.out.println("Interrupting '" + th.getClass() + "' termination");
th.interrupt();
}
}
for (Thread th : runningThreads) {
try {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.isInterrupted()) {
System.out.println("Waiting '" + th.getName() + "' termination");
th.join();
}
} catch (InterruptedException ex) {
System.out.println("Shutdown interrupted");
}
}
System.out.println("Shutdown finished");
}
});
Complete test application at github: https://github.com/idelvall/kill-test
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 like INT or TERM 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.
You can use Runtime.getRuntime().addShutdownHook(...), but you cannot be guaranteed that it will be called in any case.
Reference https://aws.amazon.com/blogs/containers/graceful-shutdowns-with-ecs/
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class ExampleSignalHandler {
public static void main(String... args) throws InterruptedException {
final long start = System.nanoTime();
Signal.handle(new Signal("TERM"), new SignalHandler() {
public void handle(Signal sig) {
System.out.format("\nProgram execution took %f seconds\n", (System.nanoTime() - start) / 1e9f);
System.exit(0);
}
});
int counter = 0;
while(true) {
System.out.println(counter++);
Thread.sleep(500);
}
}
}
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.
Related
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
It is impossible for any program, in any language, to handle a SIGKILL. This is so it is always possible to terminate a program, even if the program is buggy or malicious. But SIGKILL is not the only means for terminating a program. The other is to use a SIGTERM. Programs can handle that signal. The program should handle the signal by doing a controlled, but rapid, shutdown. When a computer shuts down, the final stage of the shutdown process sends every remaining process a SIGTERM, gives those processes a few seconds grace, then sends them a SIGKILL.
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.
Registers a new virtual-machine shutdown hook.
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
I tried the following test program on OSX 10.6.3 and on kill -9 it did NOT run the shutdown hook, as expected. On a kill -15 it DOES run the shutdown hook every time.
public class TestShutdownHook
{
public static void main(String[] args) throws InterruptedException
{
Runtime.getRuntime().addShutdownHook(new Thread()
{
#Override
public void run()
{
System.out.println("Shutdown hook ran!");
}
});
while (true)
{
Thread.sleep(1000);
}
}
}
There isn't any way to really gracefully handle a kill -9 in any program.
In rare circumstances the virtual
machine may abort, that is, stop
running without shutting down cleanly.
This occurs when the virtual machine
is terminated externally, for example
with the SIGKILL signal on Unix or the
TerminateProcess call on Microsoft
Windows.
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 the ps command looking for your program in the list and act accordingly when it disappeared.
#!/usr/bin/env bash
java TestShutdownHook
wait
# notify your other app that you quit
echo "TestShutdownHook quit"
I would expect that the JVM gracefully interrupts (thread.interrupt()) all the running threads created by the application, at least for signals SIGINT (kill -2) and SIGTERM (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:
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Interrupting threads");
Set<Thread> runningThreads = Thread.getAllStackTraces().keySet();
for (Thread th : runningThreads) {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.getClass().getName().startsWith("org.brutusin")) {
System.out.println("Interrupting '" + th.getClass() + "' termination");
th.interrupt();
}
}
for (Thread th : runningThreads) {
try {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.isInterrupted()) {
System.out.println("Waiting '" + th.getName() + "' termination");
th.join();
}
} catch (InterruptedException ex) {
System.out.println("Shutdown interrupted");
}
}
System.out.println("Shutdown finished");
}
});
Complete test application at github: https://github.com/idelvall/kill-test
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 like INT or TERM 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.
You can use Runtime.getRuntime().addShutdownHook(...), but you cannot be guaranteed that it will be called in any case.
Reference https://aws.amazon.com/blogs/containers/graceful-shutdowns-with-ecs/
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class ExampleSignalHandler {
public static void main(String... args) throws InterruptedException {
final long start = System.nanoTime();
Signal.handle(new Signal("TERM"), new SignalHandler() {
public void handle(Signal sig) {
System.out.format("\nProgram execution took %f seconds\n", (System.nanoTime() - start) / 1e9f);
System.exit(0);
}
});
int counter = 0;
while(true) {
System.out.println(counter++);
Thread.sleep(500);
}
}
}
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.
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
It is impossible for any program, in any language, to handle a SIGKILL. This is so it is always possible to terminate a program, even if the program is buggy or malicious. But SIGKILL is not the only means for terminating a program. The other is to use a SIGTERM. Programs can handle that signal. The program should handle the signal by doing a controlled, but rapid, shutdown. When a computer shuts down, the final stage of the shutdown process sends every remaining process a SIGTERM, gives those processes a few seconds grace, then sends them a SIGKILL.
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.
Registers a new virtual-machine shutdown hook.
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
I tried the following test program on OSX 10.6.3 and on kill -9 it did NOT run the shutdown hook, as expected. On a kill -15 it DOES run the shutdown hook every time.
public class TestShutdownHook
{
public static void main(String[] args) throws InterruptedException
{
Runtime.getRuntime().addShutdownHook(new Thread()
{
#Override
public void run()
{
System.out.println("Shutdown hook ran!");
}
});
while (true)
{
Thread.sleep(1000);
}
}
}
There isn't any way to really gracefully handle a kill -9 in any program.
In rare circumstances the virtual
machine may abort, that is, stop
running without shutting down cleanly.
This occurs when the virtual machine
is terminated externally, for example
with the SIGKILL signal on Unix or the
TerminateProcess call on Microsoft
Windows.
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 the ps command looking for your program in the list and act accordingly when it disappeared.
#!/usr/bin/env bash
java TestShutdownHook
wait
# notify your other app that you quit
echo "TestShutdownHook quit"
I would expect that the JVM gracefully interrupts (thread.interrupt()) all the running threads created by the application, at least for signals SIGINT (kill -2) and SIGTERM (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:
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Interrupting threads");
Set<Thread> runningThreads = Thread.getAllStackTraces().keySet();
for (Thread th : runningThreads) {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.getClass().getName().startsWith("org.brutusin")) {
System.out.println("Interrupting '" + th.getClass() + "' termination");
th.interrupt();
}
}
for (Thread th : runningThreads) {
try {
if (th != Thread.currentThread()
&& !th.isDaemon()
&& th.isInterrupted()) {
System.out.println("Waiting '" + th.getName() + "' termination");
th.join();
}
} catch (InterruptedException ex) {
System.out.println("Shutdown interrupted");
}
}
System.out.println("Shutdown finished");
}
});
Complete test application at github: https://github.com/idelvall/kill-test
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 like INT or TERM 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.
You can use Runtime.getRuntime().addShutdownHook(...), but you cannot be guaranteed that it will be called in any case.
Reference https://aws.amazon.com/blogs/containers/graceful-shutdowns-with-ecs/
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class ExampleSignalHandler {
public static void main(String... args) throws InterruptedException {
final long start = System.nanoTime();
Signal.handle(new Signal("TERM"), new SignalHandler() {
public void handle(Signal sig) {
System.out.format("\nProgram execution took %f seconds\n", (System.nanoTime() - start) / 1e9f);
System.exit(0);
}
});
int counter = 0;
while(true) {
System.out.println(counter++);
Thread.sleep(500);
}
}
}
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.
I am trying to get a shutdown hook to work on my ubuntu server, however I seem to have an issue with more than one thread. Using the a basic ShutdownHook, the following bit of code does work when I kill the process using kill <PID>, meaning the shutdown behavior is activated.
public static void main(String[] args) {
ShutdownHook shutDown = new ShutdownHook();
shutDown.attachShutDownHook();
while(true){}
}
however this same code with an additional thread does not
public static void main(String[] args) {
ShutdownHook shutDown = new ShutdownHook();
shutDown.attachShutDownHook();
(new Thread() {
public void run() {
while ( true ) {}
}
}).start();
while(true){}
}
Any ideas?
class ShutdownHook {
ShutdownHook() {
}
public void attachShutDownHook() {
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
System.out.println("Shut down hook activating");
}
});
System.out.println("Shut Down Hook Attached.");
}
}
The JVM won't exit while there are still non-daemon threads running. Try calling setDaemon(true) on your new thread.
To take an example from a project of my own;
My core class spawns a whole bunch of worker threads, the workers run transactions that must complete.
In the core class I have;
Runtime.getRuntime().addShutdownHook(new ShutdownCleanup());
Which looks something like;
public final class ShutdownCleanup extends Thread() {
public void run() {
log("waiting for worker threads to finish...");
while(WorkerThread.transactionInProgress()) {
Thread.sleep(1000);
}
//close various sockets and resources
}
}
The moment I hit Ctrl+C in the terminal, the log message appears. So the shutdown hook activates immediately, it isn't something that runs once the program is ready to die, rather it runs as soon as the close or kill request is received.
For this reason I believe what others have said about shutdown hooks never being called while there is still a thread alive is false. What would be the point of a shutdown hook that only activated once everything has died anyway?
It might be that you're using a hard kill, such as -9. Have you tried a normal shutdown with Ctrl+C or SIGINT?
java.lang.Runtime.addShutdownHook( Thread ) registers a new virtual-machine shutdown hook:
The Java virtual machine shuts down in response to two kinds of
events:
The program exits normally, when the last non-daemon thread exits or when the
exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as
typing ^C, or a system-wide event, such as user logoff or system shutdown.
Your code runs indefinitely so the shutdown hook will never be called.
[After your edit]
Which kill do you use?
kill -9 is non trappable
kill -2 may be used to emulate a ctrl-c (SIGINT)
I was going through shutdown hook feature of java , My analysis was ..shutdownhook allows to register a thread that will be created immediatly but started only when the JVM ends ! So it is some kind of "global jvm finalizer", and you can make useful stuff in this thread (for example shutting down java ressources like an embedded hsqldb server). This works with System.exit(), or with CTRL-C / kill -15 (but not with kill -9 on unix, of course).
Please advise more practical uses and please also if possibe an small example will help to make understanding more clear..!
When a shutdown hook is added to a Runtime instance, it is added to a list of Threads to start upon clean termination of the JVM.
Example: Using shutdown hook to ensure that a java.awt.TrayIcon is removed from the system tray.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
try {
if (SystemTray.isSupported()) {
SystemTray.getSystemTray().remove(yourTrayIcon);
}
} catch (Exception e) {
// failed to remove
e.printStackTrace();
}
}
});
More can be read in the offical documentation.
I have a java program that runs another (Python) program as a process.
Process p = Runtime.getRuntime().exec("program.py", envp);
If the java program finish processing, the Python process is finished as well. The finish command sends a signal to the Python process to close it.
In normal situation the process is closed this way:
BufferedWriter output = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
output.write("#EOF\n");
output.flush();
However, when the java program crashes, the process is not closed. The closing command is not send due to the crash. Is it possible to terminate the process automatically every time the program is terminated?
hey #czuk would a ShutdownHook hook be any use? This will deal with the following scenarios
The Java virtual machine shuts down in response to two kinds of events:
The program exits normally, when the last non-daemon thread exits or when the exit (equivalently, System.exit) method is invoked, or
The virtual machine is terminated in response to a user interrupt, such as typing ^C, or a system-wide event, such as user logoff or system shutdown.
When the system unexpectedly crashes this is not so easy to capture.
Perhaps use the Thread.setDefaultUncaughtExceptionHandler method?
Assuming that by crashing you mean that the Java program throws an exception, I would just kill the Python process when that happens. I haven't seen your code but:
class Foo {
Process p;
private void doStuff() throws Exception {
p = Runtime.getRuntime().exec("program.py", envp);
// More code ...
}
private void startStuff() {
try {
doStuff();
} catch (Exception e) {
p.destroy();
}
}
public static void main(String[] args) {
Foo foo = new Foo();
foo.startStuff();
}
}
Something like this should work if only exceptions that cause the program to crash escapes from doStuff().
Even if you don't expect the program to crash in this way when it is finished I think this approach is better than perhaps wrapping it in a shell script that in some way kill the Python process. Handling it in your program is less complex and it might even be a good idea to keep the code once the program is finished, since you might still have bugs that you don't know about.