Longjmp退出信号处理程序?

时间:2011-09-07 13:23:52

标签: c unix signals longjmp

从问题:

Is it good programming practice to use setjmp and longjmp in C?

其中两条评论说:

  

“你不能在信号处理程序中抛出异常,但你可以做一个   longjmp安全 - 只要你知道你在做什么。 - 迪特里希   Epp 8月31日19:57          @Dietrich:给你的评论+1。这是一个鲜为人知的   完全不被重视的事实。有很多问题   不使用longjmp就无法解决(令人讨厌的竞争条件)   信号处理程序。阻塞系统调用的异步中断是   经典的例子。“

我的印象是内核在遇到异常情况时调用信号处理程序(例如除以0)。此外,只有在您专门注册它们时才会调用它们。

这似乎暗示(对我而言)他们不会通过您的正常代码调用。

继续这个想法...我理解的是setjmp和longjmp用于将堆栈折叠到先前的点和状态。我不明白在调用信号处理程序时如何折叠堆栈,因为它从内核调用作为一次性环境而不是从您自己的代码调用。从信号处理程序到堆栈的下一步是什么!?

5 个答案:

答案 0 :(得分:16)

答案 1 :(得分:8)

longjmp does not perform normal stack unwinding。相反,堆栈指针只是从setjmp保存的上下文中恢复。

Here is an illustration了解如何在您的代码中使用非异步安全的关键部分。建议例如在关键代码中屏蔽有问题的信号。

答案 2 :(得分:1)

在大多数系统中,信号处理程序拥有自己的堆栈,与主堆栈分开。这就是为什么你可以从一个处理程序中解脱出来的原因。我认为这不是明智之举。

答案 3 :(得分:0)

值得一读:http://man7.org/linux/man-pages/man2/sigreturn.2.html关于Linux如何处理信号处理程序调用,在这种情况下,它如何管理信号处理程序退出,我的阅读建议建议从信号处理程序执行longjmp()(导致在没有sigreturn()调用的情况下,充其量只能是“未定义的” ...还必须考虑到setjmp()在哪个线程(因此是用户堆栈)上被调用,以及在哪个线程(因此也是用户堆栈)上被调用longjmp()随后也被调用!

答案 4 :(得分:-2)

您无法使用longjmp退出信号处理程序。

原因是setjmp只保存了调用约定指定应该通过普通函数调用保存的资源(进程寄存器)等。

当发生中断时,被中断的函数可能具有更大的状态,longjmp将无法正确恢复。