我有一个特殊的函数(一个信号处理程序),我想检测它的递归,即确定函数是否直接或间接调用自身。棘手的一点是该函数在某一点上调用了一些不在其控制之下的代码,并且该代码可以做任何事情。
通常情况下,我只会写一些类似
的内容void foo() {
static int recursed = 0;
if(recursed) {
...
}
recursed = 1;
othercode();
recursed = 0;
}
但在这种情况下,我担心othercode
可以使用longjmp
或类似内容突破,导致recursed
保持为1.如果我的功能是以这种方式跳出来,我想确保它不会在以后被调用时将其视为递归(事实上它是longjmp
',否则不是问题。)
注意:我认为可能会longjmp
。 othercode
是来自其他一些野外代码的链式信号处理程序,并且存在例如处理程序。使用SIGSEGV
恢复上下文的longjmp
(例如,作为“故障保护”异常处理程序)。请注意,在同步信号处理程序中使用longjmp
通常是安全的。无论如何,我并不特别在意其他代码是否安全,因为它不是我无法控制的。
答案 0 :(得分:3)
不确定代码究竟是什么样的,但是不是静态int,而是静态void *。而不是将其设置为1,将其设置为指向当前堆栈帧。除了检查它是否为非零之外,还要检查以确保recursed
之后的下一个堆栈帧的返回地址实际上指向foo代码中的某个位置,并且recursed
高于当前位置堆栈指针,即不弹出。
听起来非常脆弱且依赖于架构。
答案 1 :(得分:0)
根据signal(7)的POSIX标准,longjmp()不是可以安全地从信号处理程序内部调用的调用之一。在考虑longjmp(3)文档所说的这个问题之前,你需要确保你调用的代码使用sigsetjmp()和siglongjmp()
如果您调用的代码跳出信号处理程序,那么我不知道如何知道何时更新recursed
变量,除非您还控制此未知代码调用的回调函数回到你的申请表。