由于在信号处理期间自动屏蔽了正在被处理的信号,而使用setjmp/longjmp跳出信号处理程序时又不会自动将
信号屏蔽码修改会原来的屏蔽码,从而引起该信号被永久屏蔽。
可以使用sigsetjmp/siglongjmp来解决这一问题。
int sigsetjmp(sigjmp_buf env, int savesigs);
void siglongjmp(sigjmp_buf env, int val);
如果savesigs非0,则sigsetjmp在env中保存进程的当前信号屏蔽字,在调用siglongjmp会从其中恢复保存的信号
屏蔽字。
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#define ENV_UNSAVE 0
#define ENV_SAVED 1
int flag_saveenv = ENV_UNSAVE;
jmp_buf env; //保存待跳转位置的栈信息
void hand_min15(int);
int main()
{
switch(sigsetjmp(env, 1))
{
case 0:
{
printf("sigsetjmp
");
flag_saveenv = ENV_SAVED;
break;
}
case 1:
{
printf("return from min+15
");
break;
}
default:
break;
}
signal(SIGRTMIN+15, hand_min15);
printf("wait for signal
");
while(1);
return 0;
}
void hand_min15(int sig_num)
{
if (flag_saveenv = ENV_UNSAVE)
{
return;
}
sleep(10);
printf("after sleep
");
siglongjmp(env, 1);
printf("recv min+15
");
return;
}
说明:
1、
信号处理函数先检查 flag_saveenv 的值是否为ENV_UNSAVE,如果是,则直接返回,因为此时程序还没来得及保存返回点的栈状态信息。在sigsetjmp之后才将
flag_saveenv设置为ENV_SAVED。如果不这样处理,那么当信号发生在调用sigsetjmp之前时,信号处理函数将返回到未知地点或程序崩溃(可以在sigsetjmp前面加上sleep(20),
可以观察到程序崩溃)。使用siglongjmp从信号处理程序返回时都应该这样处理。
2、
实时信号是可靠的,支持排队
3、