如何触发默认信号处理行为? [英] How do I trigger the default signal handling behavior?
问题描述
在我的 Java 应用程序中,我想捕获 SIGINT,做一些预处理,然后让默认行为(进程终止)运行.我想我可以做这样的事情:
Signal.handle(new Signal("INT"), new SignalHandler() {@覆盖公共无效句柄(信号信号){//预处理//...//现在做默认行为SignalHandler.SIG_DFL.handle(信号);}});
但是,当我以 SIGINT
发送到此应用程序时,我得到一个 SEGV
:
似乎 SignalHandler.SIG_DFL
不打算直接调用(即使是从其他信号处理代码).那么如何手动触发呢?
或者,我如何手动复制 SIG_DFL
的行为?似乎相当于:
System.exit(signal.getNumber() + 128)
但我没有看到任何相关文件.
<小时>表达我的问题的另一种方式:
实际上*这两个代码块之间有区别吗?
A)
Signal.handle(new Signal("INT"), SignalHandler.SIG_DFL);
B)
Signal.handle(new Signal("INT"), new SignalHandler() {@覆盖公共无效句柄(信号信号){System.exit(signal.getNumber() + 128)}});
*我知道未记录的行为随时可能发生变化,但 JVM 的退出行为不太可能在中期版本发生变化.一个简单地详细说明现在发生了什么的答案在实践中是可以接受的.
最初注意到这一点的功劳归功于 RealSkeptic,但我想在答案中对其进行扩展.
SIGINT
、SIGTERM
和 SIGHUP
的默认行为实际上不是 SignalHandler.SIG_DFL
.相反,java.lang.Terminator
类 注册一个SignalHandler
,实际上只是调用Shutdown.exit()代码>:
SignalHandler sh = new SignalHandler() {公共无效句柄(信号 sig){Shutdown.exit(sig.getNumber() + 0200);}};
您可以通过调用 Signal.handle()
来捕获这个 SignalHandler
(因为它返回旧的处理程序),或者您可以简单地定义自己的调用 System.exit()
会做同样的事情.
请注意,Terminator
对 Shutdown.exit()
的调用与 System.exit() 不完全相同代码>.前者是包私有的,这意味着您不能直接调用它.如果安全管理器阻止您调用
System.exit()
,则您必须捕获原始处理程序并重用它.
警告:这是未记录的行为.Java 的未来版本不太可能但完全有可能改变这种行为.
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.
Credit for originally noticing this goes to RealSkeptic, but I wanted to expand on it in an answer.
The default behavior for SIGINT
, SIGTERM
, and SIGHUP
is not, in fact, SignalHandler.SIG_DFL
. Instead, the java.lang.Terminator
class registers a SignalHandler
that does, in fact, simply call Shutdown.exit()
:
SignalHandler sh = new SignalHandler() {
public void handle(Signal sig) {
Shutdown.exit(sig.getNumber() + 0200);
}
};
You can capture 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 thing.
Note that Terminator
's call to Shutdown.exit()
is not exactly the same as System.exit()
. The former is package-private, meaning you can't call it directly. If a security manager prevents you from calling System.exit()
, you'll have to capture the original handler and reuse it.
Warning: this is undocumented behavior. It's unlikely but entirely possible that future releases of Java could change this behavior.
这篇关于如何触发默认信号处理行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!