tags:

views:

845

answers:

6

I am investigating a Java issue (using IBM JVM 1.4.2 64-bit) on Red Hat Linux. I am wondering if anyone has seen this error message before and knows if there is a workaround to this problem?

Source:

import sun.misc.Signal;
import sun.misc.SignalHandler;

public class SignalTest extends Thread
{
    private static Signal signal = new Signal("INT");

    private static ShutdownHandler handler = new ShutdownHandler();

    private static class ShutdownHandler implements SignalHandler
    {
        public void handle(Signal sig)
        {
        }
    }

    public static void main(String[] args)
    {
        try
        {
            Signal.handle(signal, handler);
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }

        try { Thread.sleep(5000); } catch(Exception e) { e.printStackTrace(); }

        System.exit(0);
    }
}

Output:

java.lang.IllegalArgumentException <Signal already used by VM: INT>
java.lang.IllegalArgumentException: Signal already used by VM: INT
at
com.ibm.misc.SignalDispatcher.registerSignal(SignalDispatcher.java:145)
at sun.misc.Signal.handle(Signal.java:199)
at xxx

Additional Information:

I found out something strange. The reason why it fails is because I am running the program inside a shell script as a background process.

i.e. sigtest.sh:

#!/bin/bash
java -cp . SignalTest >> sigtest.log 2>&1 &

If I run the program from the command line, or remove the "&" (i.e. make it a foreground process inside the shell script), it doesn't have a problem... I don't understand why this is the case.

A: 

The exception occurs because the VM already has a signal handler put in place for SIGINT. What you can/should do about this depends upon the context in which this exception is thrown.

Brandon E Taylor
A: 

I've tried the same code and it works for me. So I guess there might be some difference in the setup.

After adding

System.out.println("Hello");

to the handle message I can run the class like that:

z@zolty:/tmp/so$ java SignalTest & sleep 1s && kill -2 $!
[1] 20467
z@zolty:/tmp/so$ Hello
z@zolty:/tmp/so$
z@zolty:/tmp/so$ java SignalTest
[1]+  Done             java SignalTest
Grzegorz Oledzki
Yes, I have two environments.One is 32 bit Linux, it works fine using Sun JVM.One is 64 bit Linux, it doesn't work on this one.
Jin Kim
My setup is 64-bit (2.6.24...) using Sun JVM (HotSpot, 1.6.0_11).
Grzegorz Oledzki
I'm starting to feel this is less a programming issue and more a JVM issue.
Jin Kim
+2  A: 

Try starting the JVM with an -Xrs option which is valid on the IBM JVM according to this anyway. That might prevent the conflict.

EDIT: In response to your underlying desire, look at:

Runtime.getRuntime().addShutdownHook(Thread)

You subclass a thread object, and it will start as part of the shutdown (take out that -Xrs for this to work well). Some things (like calling halt on Runtime) can stop that from happening, so you do need to be aware of the possibility that it just won't end up happening.

Yishai
That changes the output from:java.lang.IllegalArgumentException <Signal already used by VM: INT>to the following:java.lang.IllegalArgumentException <Signal restricted by VM: INT>
Jin Kim
+1  A: 

As written by Heinz Kabutz, the signals you are able to catch depend on the operating system you are running on and propably the JVM version. If a certain os/jvm combination does not let you register your signal then you are out of luck. Maybe tweaking with os/vm settings might help.

According to your comment, adding a shutdown hook as proposed by Yishai should do the trick.

Peter Kofler
+1  A: 

This is may very well be a JVM implementation specific problem. We are using an undocumented / unsupported API (sun.misc.Signal/SignalHandler) and therefore no contract on the behavior of the API is guaranteed.

The IBM JVM implementation could do signal-handling-related-things differently from the SUN JVM implementation and thus cause this problem. So that this specific use case works in the SUN JVM but not in the IBM JVM.

But try out the following (I can't try it out myself):

Do all combinations off starting the JVM with one/two/three of those parameters and there possible value combinations.

  1. the -Xrs option specified / not specified
  2. the property ibm.signalhandling.sigint set to true / false
  3. the property ibm.signalhandling.rs set to true / false

(The properties where found via google in several error dumps but I can't find any specific documentation on them)

I don't know if the IBM JVM also supports this special flag but you could try adding this too which in SUN JVM seems to be specific for some problems with signal handlers under linux/solaris

-XX:-AllowUserSignalHandlers

Or try using a native signal handler if that is an option for you. Check out the code samples provided:

Although it doesn't relate to your specific problem, an IBM article on JVM signal handling (slightly dated but still mostly correct). With samples for native code signal handlers:

Revelations on Java signal handling and termination


But I guess this may all be to no avail as the IBM JVM implementation could rely on handling SIGINT itself to function correctly and thus never giving you a chance to handle SIGINT yourself.

Btw. from the description to the -Xrs flag I understand that it actually may hinder you to do what you want. It says

When -Xrs is used on Sun's JVM, the signal masks for SIGINT, SIGTERM, SIGHUP, and SIGQUIT are not changed by the JVM, and signal handlers for these signals are not installed.

Or it could mean that only the JVM default actions for the signals aren't executed. Or it could depend on the JVM implementation what is really meant.

jitter
The issue was JVM specific.I had to install another JVM to get the behaviour I desired.
Jin Kim
A: 

I got this to work by using a different JVM implementation (SuSE) instead of IBM. When dealing with undocumented features, it appears that JVMs are not very consistent in behaviour.

Jin Kim