Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I trigger the default signal handling behavior?

Tags:

java

unix

signals

In my Java application I want to capture SIGINTs, do some pre-processing, and then let the default behavior (process termination) run. 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 at SIGINT to this application, I get a 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 SignalHandler.SIG_DFL is not meant to be called directly (even from other signal handling code). So how can I manually trigger it?

Alternatively, how can I manually replicate the behavior of SIG_DFL? It appears to be equivalent to:

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

but I don't see any documentation to that effect.


Another way to phrase my question:

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

A)

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

B)

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

*I know undocumented behavior could change at any time, but it's unlikely that the JVM's exit behavior will change mid-version. An answer that simply details what happens now is acceptable, in practice.

like image 335
dimo414 Avatar asked Aug 24 '15 19:08

dimo414


People also ask

What is a default signal handler?

A Default signal handler is associated with every signal that the kernel runs when handling that signal. The action that a script or program performs when it receives a signal is called the default actions. A default signal handler handles these types of different default actions.

What is the default action defined for $signal?

Ign Default action is to ignore the signal. Core Default action is to terminate the process and dump core (see core(5)).

How do signal handlers work?

A signal handler is a function which is called by the target environment when the corresponding signal occurs. The target environment suspends execution of the program until the signal handler returns or calls longjmp() . Signal handlers can be set with signal() or sigaction() .


1 Answers

I think the key to the mystery here is that SIG_DFL is 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 the segmentation violation, and instead terminates the program as expected (after printing the sample text).

like image 165
RealSkeptic Avatar answered Oct 03 '22 08:10

RealSkeptic