从问题:
Is it good programming practice to use setjmp and longjmp in C?
其中两条评论说:
“你不能在信号处理程序中抛出异常,但你可以做一个 longjmp安全 - 只要你知道你在做什么。 - 迪特里希 Epp 8月31日19:57 @Dietrich:给你的评论+1。这是一个鲜为人知的 完全不被重视的事实。有很多问题 不使用longjmp就无法解决(令人讨厌的竞争条件) 信号处理程序。阻塞系统调用的异步中断是 经典的例子。“
我的印象是内核在遇到异常情况时调用信号处理程序(例如除以0)。此外,只有在您专门注册它们时才会调用它们。
这似乎暗示(对我而言)他们不会通过您的正常代码调用。
继续这个想法...我理解的是setjmp和longjmp用于将堆栈折叠到先前的点和状态。我不明白在调用信号处理程序时如何折叠堆栈,因为它从内核调用作为一次性环境而不是从您自己的代码调用。从信号处理程序到堆栈的下一步是什么!?
答案 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
将无法正确恢复。