我的系统是ubuntu 12.04。我从修改了示例man 2 signalfd
,并添加了示例sigaddset(&mask, SIGSEGV)
。但是SIGSEGV
生成时我无法获得输出。
是一个错误glibc
吗?源代码的片段如下:
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT);
sigaddset(&mask, SIGSEGV);
/* Block signals so that they aren't handled
according to their default dispositions */
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
handle_error("sigprocmask");
sfd = signalfd(-1, &mask, 0);
if (sfd == -1)
handle_error("signalfd");
int* a = NULL;
for (;;) {
s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
if (s != sizeof(struct signalfd_siginfo))
handle_error("read");
if (fdsi.ssi_signo == SIGINT) {
printf("Got SIGINT\n");
(*a) = 1;
} else if (fdsi.ssi_signo == SIGQUIT) {
printf("Got SIGQUIT\n");
exit(EXIT_SUCCESS);
} else {
printf("Read unexpected signal\n");
}
}
请参阅此答案以及该答案以获取详细说明。仔细阅读signal(7)和signal-safety(7)。也请记住,虚拟地址空间的的过程中是常见的,和之间,所有的共享线程是进程。另请参见proc(5)(并使用pmap(1)),并尝试/proc/self/maps
从您的进程内部进行读取以了解其实际的虚拟地址空间。
概括地说,如果您SIGSEGV
使用signalfd(2)处理(异步)(在发生异常错误后由内核生成),则好像您安装了“内核”信号处理程序,该信号处理程序神奇地“写入”了某些文件中的某些字节描述符(signalfd
通过在某个管道上安装信号处理程序,您几乎可以模仿一下;但是可以signalfd
保证您不会有其他的“原子性”)。
当您从该处理中返回时,机器处于相同状态,因此SIGSEGV再次发生。
如果要处理SIGSEGV
,则需要使用sigaction(2)或过时的方法signal(2)
来安装处理例程(因此不能signalfd
用于SIGSEGV),然后应该
ucontext_t
通过安装)到处理程序sigaction
与SA_SIGINFO
),例如通过改变一些寄存器,或改变它的地址空间(例如,从处理程序内部调用mmap(2))。洞察力是输入了SIGSEGV处理程序,并将程序计数器设置为故障机器指令。当您从SIGSEGV处理程序返回时,寄存器处于给定的状态(指针ucontext_t
作为sa_sigaction
传递给的函数的第三个参数sigaction
)。如果不更改该状态,则将重新执行相同的机器指令,并且由于未更改任何内容,因此会发生相同的错误,并且内核会再次发送相同的SIGSEGV信号。
顺便说一句,Ravenbrook
MPS
垃圾收集库是一个巧妙且非便携地处理SIGSEGV的软件的很好示例。它们的写屏障(按照GC的说法)是通过处理SIGSEGV来实现的。这是非常聪明的(非便携式)代码。
注意:实际上,如果您只想显示回溯信息,则可以从SIGSEGV
处理程序中进行处理(例如,通过使用GCC
libbacktrace
或backtrace(3)然后_exit(2)
-ing而不是从SIGSEGV
信号处理程序中返回);它不是完美的,并且将永远无法工作(例如,如果您破坏了内存堆),因为您将调用非异步信号安全函数,但实际上效果很好。最近的GCC正在这样做(在编译器(例如cc1plus
,及其插件)内部),并且对您有很大帮助。
由于找不到文件,send方法返回null BufferedReader。Eclipse只是说有一个NullPointerException是因为print方法,但是当我移除所有try/catch语句时,Eclipse说我需要编写方法抛出IOException或FileNotFoundException,它也允许我这样做,如果我不这样做,它就抛出一个FileNotFoundException。然而,
在try块中为未抛出异常子类的方法捕获异常,将无法编译。当我捕捉到异常时,它起作用了。它是如何工作的??
问题内容: 在有效的Java(第275页)中,有以下代码段: 捕获中断异常以重新引发它有什么用?为什么不让它飞呢? 问题答案: 简单的答案是,这是一个检查的异常,它不在方法(或方法)的签名中。所以你必须抓住它。一旦发现它,建议您设置为设置中断标志。除非您确实打算压缩中断。
参考:通配符捕获辅助方法 它说创建一个助手方法来捕获通配符。 仅使用下面的函数不会产生任何编译错误,并且似乎以同样的方式工作。我不明白的是:为什么你不直接使用这个,避免使用助手? 我认为这个问题真的可以归结为:通配符和泛型有什么区别?所以,我去了这个:通配符和泛型之间的区别。它说使用类型参数: 1)如果你想对不同类型的方法参数强制执行某种关系,你不能用通配符来做到这一点,你必须使用类型参数。 但是
问题内容: 在Java中,引发 检查 异常(Exception或其子类型- IOException,InterruptedException等)的方法必须声明 throws 语句: 不声明语句的 方法不能 引发检查的异常。 但是在Java中使用安全方法捕获检查的异常仍然合法: 其实没有 有点可笑:编译器知道 e 不是检查的异常,因此可以将其重新抛出。事情甚至有些荒谬,此代码无法编译: 第一个片段是
这个问题与前一个问题相关,在前一个问题中,我们注意到init捕获lambdas与Boost的范围和迭代器不兼容,因为一些相当模糊且嵌套很深的故障可能很难通过破解Boost来解决。射程源。 接受的答案建议将lambda存储在对象中。为了避免潜在的函数调用开销,我编写了两个函数对象,可以作为潜在的解决方法。它们在下面的代码中被称为和 不使用和编译行,并正确打印行的的实例。 然而,标准草案提到 5.1.