How to trigger default signal processing behavior?

In my Java application, I want to capture SIGINT, do some preprocessing, and then start the default behavior (process termination). I would think I could do something like this:

Signal.handle(new Signal("INT"), new SignalHandler() { @Override public void handle(Signal signal) { // preprocessing // ... // now do default behavior SignalHandler.SIG_DFL.handle(signal); } }); 

However, when I send to SIGINT in this application, I get SEGV :

 # # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x0000000000000000, pid=10261, tid=21507 # # JRE version: Java(TM) SE Runtime Environment (8.0_51-b16) (build 1.8.0_51-b16) # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.51-b03 mixed mode bsd-amd64 compressed oops) # Problematic frame: # C 0x0000000000000000 # # Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again # # An error report file with more information is saved as: # /private/tmp/hs_err_pid10261.log # # If you would like to submit a bug report, please visit: # http://bugreport.java.com/bugreport/crash.jsp # The crash happened outside the Java Virtual Machine in native code. # See problematic frame for where to report the bug. # Abort trap: 6 

It seems that SignalHandler.SIG_DFL not intended to be called directly (even from another signal processing code). So how can I manually start it?

Alternatively, how can I manually reproduce the behavior of SIG_DFL ? It seems equivalent:

 System.exit(signal.getNumber() + 128) 

but I do not see any documentation on this.


Another way to talk about my question:

In practice * is there a difference between the two code blocks?

A)

 Signal.handle(new Signal("INT"), SignalHandler.SIG_DFL); 

IN)

 Signal.handle(new Signal("INT"), new SignalHandler() { @Override public void handle(Signal signal) { System.exit(signal.getNumber() + 128) }}); 

* I know that undocumented behavior can change at any time, but it is unlikely that the behavior of the JVM output will change in the middle of the version. The answer, which simply details what is happening now, is acceptable in practice.

+4
source share
3 answers

The loan, initially noticing this, refers to RealSkeptic , but I wanted to expand it in return.

The default behavior for SIGINT , SIGTERM and SIGHUP is not really SignalHandler.SIG_DFL . Instead, the java.lang.Terminator class registers a SignalHandler , which actually just calls Shutdown.exit() :

 SignalHandler sh = new SignalHandler() { public void handle(Signal sig) { Shutdown.exit(sig.getNumber() + 0200); } }; 

You can write this SignalHandler by calling Signal.handle() (since it returns the old handler), or you can simply define your own handler that calls System.exit() , which will do the same.

Note that calling Terminator for Shutdown.exit() does not exactly match System.exit() . The first is a closed package, i.e. You cannot call it directly. If the security manager forbids you to call System.exit() , you will have to grab the original handler and reuse it.

Warning: this is undocumented behavior. It is unlikely, but entirely possible, that future releases of Java may change this behavior.

+2
source

I think the key to the secret here is that SIG_DFL not the original handler for SIGINT.

The following code worked for me:

  Signal sigInt = new Signal("INT"); // First register with SIG_DFL, just to get the old handler. final SignalHandler oldHandler = Signal.handle(sigInt, SignalHandler.SIG_DFL ); // Now register the actual handler Signal.handle(sigInt, new SignalHandler(){ @Override public void handle(Signal signal) { System.err.println("Sigint is being handled"); oldHandler.handle(signal); } }); 

This does not cause a segmentation violation and instead terminates the program as expected (after printing a sample text).

+3
source

The output from the 128+ signal seems to be typical of Unix / Linux.

For more information, see also:

Viewing the source code in OpenJDK suggests that the default behavior is to allow the current C Runtime or OS default action.

In any case, this is only typical behavior, and, as you point out, is not documented. The exit codes are not standardized - usually there is an agreement that zero means success and non-zero failure, but even the first part is not always respected. Therefore, you need to define your own exit codes.

+1
source

All Articles