Ida*_*n K 14 c++ java linux multithreading signals
我们有一个带有嵌入式JVM(Sun)的C++应用程序.因为我们注册了自己的信号处理程序,所以建议我们在初始化JVM之前这样做,因为它安装了自己的处理程序(参见此处).
根据我的理解,JVM内部知道信号是否源自其自己的代码,如果不是它将链路传递给我们的处理程序.
我们开始看到的是我们正在获得SIGPIPE,其调用堆栈看起来大致相同(顶部条目是我们的信号处理程序):
/.../libos_independent_utilities.so(_ZN2os32smart_synchronous_signal_handlerEiP7siginfoPv+0x9) [0x2b124f7a3989]
/.../jvm/jre/lib/amd64/server/libjvm.so [0x2aaaab05dc6c]
/.../jvm/jre/lib/amd64/server/libjvm.so [0x2aaaab05bffb]
/.../jvm/jre/lib/amd64/server/libjvm.so(JVM_handle_linux_signal+0x718) [0x2aaaab05e878]
/.../jvm/jre/lib/amd64/server/libjvm.so [0x2aaaab05bf0e]
/lib64/libpthread.so.0 [0x3c2140e4c0]
/lib64/libpthread.so.0(send+0x91) [0x3c2140d841]
/.../jvm/jre/lib/amd64/libnet.so [0x2aaabd360269]
/.../jvm/jre/lib/amd64/libnet.so(Java_java_net_SocketOutputStream_socketWrite0+0xee) [0x2aaabd35cf4e]
[0x2aaaaeb3bf7f]
Run Code Online (Sandbox Code Playgroud)
似乎JVM决定将从中提出的SIGPIPE send传递给我们的信号处理程序.这样做是对的吗?
另外,为什么调用堆栈不完整?我的意思是显然它不能告诉我以前的java代码,socketWrite0但为什么我不能在java代码之前看到堆栈?
JVM无法判断SIGPIPE是来自它自己的代码还是代码.该信息不是由信号给出的.因为它不希望你错过你可能感兴趣的任何可能的事件,所以它必须传递给你所有的SIGPIPE,甚至它所发出的是来自它自己的代码.
Unix信号有两种形式 - "同步"和"异步".仅执行代码时的一些特殊情况可能导致陷阱并导致"同步"信号.这些是诸如未对齐的内存访问(SIGBUS),非法内存访问,通常为NULL,(SIGSEGV),除以零和其他数学错误(SIGFPE),不可解码指令(SIGILL)等等.它们具有精确的执行上下文,并直接传递给导致它们的线程.信号处理程序可以查找堆栈并看到"嘿,我有一个执行java代码的非法内存访问,指针是NULL.让我去修复它."
相反,与外部世界交互的信号是"异步"变体,包括SIGTERM,SIGQUIT,SIGUSR1等.这些信号没有固定的执行上下文.对于线程程序,它们几乎随机地传递给任何线程.重要的是,SIGPIPE就是其中之一.是的,在某种意义上,它通常与一个系统调用相关联.但是(例如)很可能有两个线程监听两个独立的连接,这两个连接在调度任一线程之前关闭.内核只是确保有一个SIGPIPE挂起(通常的实现是待处理信号的位掩码),并在重新安排进程中的任何线程时处理它.
(至于读取调用发生了什么,它们返回"有错误:EINTR"并继续.此时,JVM可以将其转换为异常,但是在信号传递和信号处理程序触发后返回.)
结果是你只需处理假阳性.(并且只处理一个可能预期有两个信号的信号.)
| 归档时间: |
|
| 查看次数: |
2890 次 |
| 最近记录: |