5

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.");
    }   
}
Reese
  • 173
  • 3
  • 7
  • 4
    `kill -9` is the guaranteed UNIX I-don't-care-if-you're-printing-rainbows-you-will-halt-NOW flag. Using that wouldn't give you a nice shutdown. It also cannot be trapped. What I'm wondering is if you're using `System.exit()` anywhere in your code - that may be a good start. – Makoto Oct 25 '12 at 18:42
  • This article ([link](http://www.ibm.com/developerworks/java/library/i-signalhandling/)) seems to indicate that SIGTERM generates a Java System.exit(), and therefore exit hooks should work. Have you tested the hook behavior by generating a System.exit() in the JVM? – le3th4x0rbot Oct 25 '12 at 18:44
  • Probably you are using wrong PID. – Roman C Oct 25 '12 at 18:51
  • Hmm, strange indeed. You are right. I added a `System.exit(0);` call after inserting the hook. In my Eclipse env on windows, I see the shutdown hook being applied, but when I jar it up and port it to my unix server, I see the app closing, but no shut down hook... – Reese Oct 25 '12 at 18:52
  • @Roman it is definitely the right PID – Reese Oct 25 '12 at 18:56

3 Answers3

6

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);
   }
});
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    But `kill -9` as in the question can never be trapped. – Ingo Kegel Oct 25 '12 at 18:44
  • @IngoKegel: Very true, Unix designers built SIGKILL (9) like that only so that no program can ignore/handle that signal. – anubhava Oct 25 '12 at 18:45
  • 1
    So your answer does not apply to the question. Also, trapping kill signals for cleanup purposes is done with shutdown hooks, you don't really need the classes from the `sun.misc.` package for that. – Ingo Kegel Oct 25 '12 at 18:48
4

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.

Ingo Kegel
  • 46,523
  • 10
  • 71
  • 102
  • I tried both `kill -9` and `kill`, I'm just not seeing the shutdown hook applied. I also tried inserting a `System.exit(1)` into my code but when I run it as a jar through unix, I don't see the shutdown hook activating – Reese Oct 25 '12 at 19:00
  • In general `kill` (without -9) and `System.exit(1)` will definitely execute shutdown hooks. It seems that your JRE is not able to trap these signals for some reason. You could try with a different JRE. – Ingo Kegel Oct 26 '12 at 08:07
  • I'm running on my ubuntu server: java version "1.6.0_23" OpenJDK Runtime Environment (IcedTea6 1.11pre) (6b23~pre11-0ubuntu1.11.10.2) OpenJDK Client VM (build 20.0-b11, mixed mode, sharing) – Reese Oct 26 '12 at 15:49
0

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).

i30817
  • 1,356
  • 2
  • 13
  • 26