|
The Java Specialists' Newsletter
Issue 043 2002-03-11
Category:
Language
Java version: Arrgh, someone wants to kill me!by Dr. Heinz M. Kabutz
Welcome to the 43rd edition of The Java(tm) Specialists'
Newsletter, sent to 2885 Java experts in over 75 countries.
This time, I am writing from a rather cold Deutschland (for my
likings), though the inhabitants tell me it is actually quite
warm again, and I get funny looks when I walk around wearing a
thick jacket and a wooly hat. Whereas on South African roads,
I am the speed king with my Alfa Romeo, here I drive in the slow
lane (at 140km/h), so that the trucks can overtake me. Traffic
is quite interesting here in the good ol' Germany. Did you know
that since February, you are not allowed to use your indicators
at a traffic circle in Germany?
Whilst I am in Germany, I would like to organise a
Java_Specialist_Treff get-together for my European readers
so we can get the opportunity to meet each other. I will
discuss some of my newsletters, we'll have some drinks together,
basically have a nice, nerdy time ;-))) The meeting will be held
in Karlsruhe, Baden-Württemberg, close to the French border. I
have not fixed a date and time yet, so if you would like to
attend, please
send me a quick email and tell me what dates until 28th of
April would be most suitable for you.
Thanks for reading this newsletter on our website. We also have a mailing list. That is where the real action takes place (webinars, free reports, etc.). Maybe subscribe today?
Advanced Java Courses on Crete:Java Specialists Master Course 18-21 June 2013 and
Concurrency Specialists Course 6-9 August 2013.
Arrgh, someone wants to kill me!
Approximately a year ago, I wrote a newsletter about
hooking into the shutdown
call. In that newsletter, I
rather snidely remarked that the shutdown process had some
deficiencies, which rendered it useless for situations where you
want to abort the shutdown process and go back to the program.
Once you're in shutting down state, the program will die.
After I published that newsletter, a South African friend, James
Pereira, sent me a code snippet that used OS signals directly for
detecting when the program was being closed. You can use this
mechanism to write your own shutdown hook mechanism (even for JDK
1.2), and put in whatever features you need.
The code that he sent me used some classes from the sun.*
packages to achieve this. Warning: The classes in the sun.*
package hierarchy can be changed at the whim of Sun's fancy. In
addition, you will probably not find a sun.* hierarchy in any VMs
except Sun's, though I have not looked yet. The package that
James pointed me to was sun.misc, containing a
flea-market (i.e. jumble-sale) of classes, some useful, others
badly designed. You've been warned - so please don't whinge if
this does not work exactly like this on your IBM / MS / whatever
VM.
When you press Ctrl+C in the command window, an OS signal is
generated called SIGINT. This is the same on Windows and Unix.
When you kill a program by pressing the little cross, or using
your task manager, a SIGTERM signal is sent to your program, and
it will not be back! What we can do is link into the signal
handler and handle that signal any way we want to. For example:
import sun.misc.Signal;
import sun.misc.SignalHandler;
/**
* The idea for this code came from James Pereira, this code
* looks quite different to the well-structured, logically
* named class he sent me.
* The idea is that we register a handler for a Ctrl+C
* signal and then handle it.
*/
public class Aaarggh {
public static void main(String[] args) throws Exception {
Signal.handle(new Signal("INT"), new SignalHandler () {
public void handle(Signal sig) {
System.out.println(
"Aaarggh, a user is trying to interrupt me!!");
System.out.println(
"(throw garlic at user, say `shoo, go away')");
}
});
for(int i=0; i<100; i++) {
Thread.sleep(1000);
System.out.print('.');
}
}
}
When you run this program, it will print dots onto the console
and if you try to stop it with Ctrl+C, it will give you the
following output and merrily carry on printing dots. You can
either stop it by waiting for the 100 seconds or to kill it via
the task manager. (Kill sends a SIGTERM signal, which is
stronger than SIGINT)
.........Aaarggh, a user is trying to interrupt me!!
(throw garlic at user, say `shoo, go away')
..
Inside the signal handler you can do anything you want to,
including calling System.exit(0) or
Runtime.getRuntime().halt(0) if you
don't want shutdown hooks to be called.
What signals can you catch? The answer to that question depends
on the operating system you are running on. I managed
to dig out a list for Windows and Solaris Sun JDK 1.2.2:
- Windows:
ABRT, FPE, ILL, INT, SEGV, TERM
- Solaris:
ABRT, ALRM, BUS, CHLD, CONT, EMT, FPE, HUP, ILL, INT, IO, KILL,
PIPE, POLL, PROF, PWR, QUIT, SEGV, STOP, SYS, TERM, TRAP, TSTP
TTIN, TTOU, URG, USR1, USR2, VTALRM, WINCH, XCPU, XFSZ
Please don't ask me what events generate each of those signals.
It's a miracle that I found that list of signals,
sun.misc.Signal is written in such a way that if you
pass in an incorrect String it throws an IllegalArgumentException
at you. However, it does not tell you what the possible signals
are. The most significant signals from within Java are
SIG and TERM.
Here is some code that is called whenever our program is killed:
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class SophisticatedShutdownSequence {
private static boolean running = true;
public static void init() {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("reached point of no return ...");
}
});
SignalHandler handler = new SignalHandler () {
public void handle(Signal sig) {
if (running) {
running = false;
System.out.println("Signal " + sig);
System.out.println("Shutting down database...");
} else {
// only on the second attempt do we exit
System.out.println(" database shutdown interrupted!");
System.exit(0);
}
}
};
Signal.handle(new Signal("INT"), handler);
Signal.handle(new Signal("TERM"), handler);
}
public static void main(String args[]) throws Exception {
init();
Object o = new Object();
synchronized (o) {
o.wait(10000);
}
System.exit(0);
}
}
If you run this and press Ctrl+C twice, or try kill the program
once via task manager or by pressing the cross, you get the
following output:
Signal SIGINT
Shutting down database...
database shutdown interrupted!
We have now reached the point of no return ...
This shutting down sequence is a good opportunity for the State
Pattern (see Gang of Four book). Due to popular request, I will
try and show one Java Design pattern every 4 newsletters, and I
might just start with the State Pattern. In addition, I will
soon start doing book reviews on books that you should definitely
have in your bookshelf.
Switching off OS signals at runtime
In JDK 1.3.1, Sun sneaked in a JVM runtime parameter to stop all
this nonsense of hooking into signals.
public class NoShutdownHookAllowed {
public static void main(String[] args) throws Exception {
try {
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
System.out.println("Shutdown hook going mad");
}
});
} catch(IllegalArgumentException ex) {
System.out.println("Caught " + ex);
}
Thread.sleep(10000);
}
}
Try running this with JDK 1.3.1 and beyond, and use the following
command: java -Xrs NoShutdownHookAllowed The -Xrs
setting reduces use of OS signals by Java/VM.
What happens is that an IllegalArgumentException is generated
after the thread has been added as a shutdown hook. This means
that if you try to interrupt the code after it has been started,
the shutdown hook will not be called. However, if you let
the program finish naturally, it will run the shutdown hook. As
far as I know, the -Xrs option is there to make it
easier to write services in Java.
Also dann, bis nächste Woche...
Heinz
Language Articles
Related Java Course
Discuss at The Java Specialist Club
|