I have a product service in Java. In our code I am creating shut down hook, but when I stop service it is not calling shut down hook consistently. Out of 5 stop calls it has called shutdown hook only once.
Runnable shutdownHandler = new Runnable() {
#Override
public void run() {
s_log.info("Shutting down thread..");
}
};
Runtime.getRuntime().addShutdownHook(
new Thread(shutdownHandler, "shutdownthread"));
Can anybody please tell me what could be the reason behind this not getting called consistently?
Check the following code:
Runnable shutdownHandler = new Runnable() {
#Override
public void run() {
System.out.println("Shutting down thread..");
}
};
Runtime.getRuntime().addShutdownHook(
new Thread(shutdownHandler, "shutdownthread"));
and if it gives you expected output, you need to check the documentation of your logging framework.
I am also finding that my framework (Jooby) and Java shutdown hooks work fine on my Mac on IntelliJ which sends a kill SIGINT (-2) however on Ubuntu Server 20.04 LTS they don't run.
As my Java app is a webapp I came up with a simple workaround:
Setup a controller to listen to some url that isn't easily guessable e.g.
/exit/fuuzfhuaBFDUWYEGLI823y82941u9y47t3u45
Have the controller simply do the following:
System.exit(0)
Do a curl or wget from a script to the URL and the shutdown hooks all fire as JVM comes down.
I suspect for some reason on Linux there is a bug and no matter what interrupt that I use besides SIGKILL they all effectively behave like SIGKILL and the JVM comes down hard/abruptly.
Related
In my application I have written the shut down hook. But some third party code is calling that shut down hook.
This shut down hook should not be called by any third party code.
I have written the code to block shut down hook by third party but it did not help. (This code worked in my standalone test program. but did not worked in my application.)
Below are the code where something different behaviour is occurring:
final SecurityManager securityManager = new SecurityManager() {
public void checkPermission(Permission permission) {
System.out.println("In checkPermission:{" + permission.getName() + "}");
if ("exitVM.0".equals(permission.getName())) {
throw new ExitTrappedException();
}
}
};
When I execute this code in Test program then when shut down being called its giving me "In checkPermission:{exitVM.0}". So that it comes in if condition and my shut down hook gets blocked.
Now when I tried same thing in my application then this "exitVM.0" is not getting printed and shut down hook is getting called.
Any suggestions? Is there any different permission.getName() which can call shutdown hook?
It could be exitVM.1, exitVM.2, etc, since the number is just the shutdown code. The actual permission is called exitVM. (see http://docs.oracle.com/javase/7/docs/technotes/guides/security/permissions.html). So you could use permission.getName().startsWith("exitVM").
But what you're trying to do (prevent application being shut down) sounds like it might not be the best idea. What's the context?
I am trying to come up with a microservice using dropwizard.
The documentation tells how to start the application, but says nothing about terminating it gracefully. Fir example, apache tomcat has both startup and shutdown scripts.
So does anyone know how to terminate a dropwizard application other than pressing Ctrl+C of kill ?
Dropwizard Jetty has shutdown hooks. So kill -SIGINT <pid> works out really well.
Inspired by praveenag's answer, I dug into Jetty's code.
If you start DropWizard providing:
-DSTOP.PORT=xxxx -DSTOP.KEY=my_secret_key
as Java options,
It tells Jetty to listen on that port for a stop request.
You can then write to that socket to tell Jetty to shutdown. I did this from R like this:
socket = make.socket("localhost", 8082)
write.socket(socket, "my_secret_key\r\n")
write.socket(socket, "stop\r\n")
close.socket(socket)
I guess you can do the same from any other language.
The other answers here are great, but if you want to go a bit further up the stack and easily add custom logging / security / arbitrarily complex shutdown logic, then adding a shutdown hook via a dropwizard admin Task is a nice pattern.
Create a shutdown Task with any logic you like
import io.dropwizard.servlets.tasks.Task;
public class ShutdownTask extends Task {
public ShutdownTask() {
super("shutdown"); // the task name, used in the endpoint to execute it
}
public void execute(
ImmutableMultimap<String, String> immutableMultimap,
PrintWriter printWriter
) throws Exception {
// kill the process asynchronously with some nominal delay
// to allow the task http response to be sent
new Timer().schedule(new TimerTask() {
public void run() {
// any custom logging / logic here prior to shutdown
System.exit(0);
}
}, 5000);
}
}
Register the task in Application.run()
environment.admin().addTask(new ShutdownTask());
And then execute it via a POST to the following endpoint on the admin port
http://localhost:<ADMIN PORT>/tasks/shutdown
I am assuming this is not a question for your development environment but for your deployments. The answer depends on your deployment strategy. In the past we have handled deployments where the drop wizard application is bundled as a java process that can be started and the pid being recorded and forcefully kill the process. Or bundle the java process in an upstart/init script to gracefully start and shutdown the system.
On the other hand when you start a dropwizard application what it eventually does is start a jetty server. http://eureka.ykyuen.info/2010/07/26/jetty-stop-a-jetty-server-by-command. This can maybe shed some light on how you can pass the stop port as arguments when you start the dropwizard application.
Programmatically, you can also do:
environment.getApplicationContext().getServer().stop();
That's the environment you get in your Application:
#Override
public void run(ApplicationConfiguration configuration, Environment environment) throws Exception { ... }
In Java:
// In case vm shutdown
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run()
{
// what should be closed if forced shudown
// ....
LOG.info(String.format("--- End of ShutDownHook (%s) ---", "APPLICATION_NAME"));
}
});
Build your own strategy, how to shutdown your app.
Is it possible to schedule a executable file to run just before log-off using java?
I am working on a application that needed to send a message to the sever just before the system log-off/shutdown. But I didn't find any method to solve it. If anyone know plz help me.
Thanks in advnce.
As stated in the comments a ShutdownHook is probably what you are searching for.
Short example:
Runtime.getRuntime().addShutdownHook(new Thread() {
#Override
public void run() {
// Code to be executed when JVM exits
System.out.println("JVM exit");
}
});
Note that the ShutdownHook will execute whenever the JVM exits. So it will also execute when your program terminates normally.
If you have any further questions comment on this answer.
Ive got the following ShutdownHook to detect when the application is exited:
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
// Do what you want when the application is stopping
sendMsg("", "goOfflineExit", "12");
}
}));
This works perfectly on Mac os but for some reason nothing gets fired on Windows.
Any ideas what im missing?
I can think of two possible explanations:
The sendMsg(...) call may be happening too late; e.g. after streams have been closed or flushed.
The sendMsg(...) call may be throwing an exception. Uncaught exceptions thrown in a shutdown hook typically don't get reported.
If you showed us the code of sendMsg we might be able to figure out a more definite answer.
I am trying to get my Java program to exit gracefully on my unix server. I have a jar file, which I start through a cron job in the morning. Then in the evening, when I want to shut it down, I have a cron job which calls a script that finds the PID and calls kill -9 <PID>. However, it doesn't seem that my shutdown hook is activated when I terminate this way. I also tried kill <PID> (no -9) and I get the same problem. How can I make sure the shutdown hook gets called? Alternatively, perhaps there is a better way to kill my process daily.
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.");
}
}
You can use code like this on Unix to trap SIGINT (#2) signal:
Signal.handle(new Signal("INT"), new SignalHandler() {
public void handle(Signal sig) {
// Forced exit
System.exit(1);
}
});
kill -9 <pid> sends a KILL signal. This signal cannot be intercepted by the program.
If you call kill <pid>, the TERM signal (15) wil be sent. In that case, the JVM will catch the signal and the shutdown hooks will be executed.
This has nothing to do with the signals the JVM is trapping/receiving but everything to do with the terrible shutdown process of Gnome, which apparently needs to be cooperative not to absolutely shit the bed (and the jdk doesn't have the api for this). If you want to see a even worse consequence of this, try to run:
dbus-monitor --profile --session type='method_call',interface='org.gnome.SessionManager'
on a shell, and logout or restart: it will crash gnome-shell and hang the computer until you login on a TTY and order a restart.
Maybe kdbus will fix this on this case, maybe not. The only thing i know is that shutdownhooks on a java application that is using AWT (not command line) will NEVER run its shutdownhooks on GNOME3. Actually, the VM will always exit with non-zero code (failure) presumably from native code. At least it doesn't hang, although this makes shutdown hooks quite useless
(i've been trying to make a workaround by using dbus-monitor, but as you can see from the example i gave, it's a bit too dangerous too).