我正在使用sigsetjmp和singlongjmp与SIGALARM中断系统调用,如下面的代码所示
//data of Alarm_interrupter
void (TClass::*fpt)(const char*); // pointer to member function
TClass* pt2Object; // pointer to object
===================================================
//for timeout processing
static sigjmp_buf jmpbuf;
static void recvfrom_alarm(int) {
siglongjmp(jmpbuf, 1);
}
======================================================
void Alarm_interrupter::start_timeout() {
signal(SIGALRM, recvfrom_alarm);
alarm(timeout);
(*pt2Object.*fpt)("timeouted before sigsetjmp"); //this call works OK
if (sigsetjmp(jmpbuf,1) != 0) {
//at this point, pt2Object is still OK,
//but fpt seems to point to nothign.
(*pt2Object.*fpt)("timeouted after sigsetjmp");
}
return;
}
==============================================================
在sigsetjmp returnn 1之前,使用object和方法指针调用:* pt2Object。* fpt(“sigsetjmp之前的时间”)是正常的,但是在sigsetjmp返回1之后,此调用失败。 检查变量状态后,我注意到对象指针“pt2Object”仍然是Ok,但方法指针“fpt”似乎不同。
我认为一个可能的原因是sigsetjmp无法恢复整个早期环境,其中包括方法指针“fpt”。
你可以帮我解决这个问题。非常感谢!答案 0 :(得分:1)
正如Potatoswatter指出的那样,使用闹钟推迟longjmp
是太聪明了,无法依靠。你必须先调用'sigsetjmp'。它必须在之前发生你试图返回那里。
sigsetjmp
或setjmp
唯一可行的方法是遵循此伪代码。
if (sigsetjmp(...) != 0) {
// Error handling code
}
// code that might call siglongjmp to bail out to Error handling code
你知道,必须执行一次才能执行上下文的保存。这会初始化jmpbuf
。如果您在执行前没有调用longjmp
而调用setjmp
,则无法预测该行为。
此外,longjmp
将倾向于删除您可能尝试使用的任何局部变量。
int var = 3;
var = 2;
if (sigsetjmp(...) != 0) {
// Error handling code
printf("%d", var); // could print 2, 3 or even "potato". Local vars get trashed.
}
// code that might call siglongjmp to bail out to Error handling code
所以你真的想在 *setjmp
之后做一切有趣的事情。
int var = 3;
if (sigsetjmp(...) != 0) {
// Error handling code
var = 2;
printf("%d", var); // now you know it's 2
}
// code that might call siglongjmp to bail out to Error handling code
如果希望它在*longjmp
中存活,则需要将其标记为volatile
。
volatile int var = 3;
var = 2;
if (sigsetjmp(...) != 0) {
// Error handling code
printf("%d", var); // probably 2
}
// code that might call siglongjmp to bail out to Error handling code
即使这可能还不够。它可能需要被称为sigatomic_t或类似的东西。但尽量不要像那样疯狂。
int var = 3;
memcpy(var, (int *){2}); //memcpy is pretty reliable (C99ism: immediate pointer))
if (sigsetjmp(...) != 0) {
// Error handling code
printf("%d", var); // probably 2
}
// code that might call siglongjmp to bail out to Error handling code