/**
* @file test_try_catch.c
* @Brief 使用形如C++的异常来检测超时
* @author email:huangkq1989@gmail.com blog:http://blog.csdn.net/kangquan2008
* @version 1.0
* @date 2013-10-22
*/
#include
#include
#include
#include
#include
#define __WITH_TIME_OUT_IMPOSSIBLE__
#ifdef __WITH_TIME_OUT_IMPOSSIBLE__
static sigjmp_buf __time_out_jump;
typedef void (* __sigfunc)(int);
static void __do_time_out(int sig)
{
fprintf(stdout,"time out here\n");
siglongjmp(__time_out_jump, 1);
}
static void __time_out_reset(__sigfunc store)
{
alarm(0);
signal(SIGALRM, store);
}
#define TIME_OUT_TRY(x) \
{\
// 设置超时处理函数,将调用longjmp,使得能进入else,即catch
__sigfunc save = signal(SIGALRM, __do_time_out);\
// 保存堆栈,返回值为0时表示不是由longjmp返回,
// 否则为调用了longjmp后返回的
// 参数 1,是为了保存当前进程的信号屏蔽字
if(!sigsetjmp(__time_out_jump, 1)) {\
//计时
alarm(x);
#define TIME_OUT_CATCH \
}\
// 由于sigsetjmp返回非0,进入CATCH
else {\
#define TIME_OUT_END \
} \
// 恢复SIGALRM的信号处理函数
__time_out_reset(save);\
}
#define TIME_OUT_RETURN(x) { __time_out_reset(save); return (x); }
#define TIME_OUT_RETUR_VOID { __time_out_reset(save); return ; }
#endif //__WITH_TIME_OUT_IMPOSSIBLE__
int main()
{
int timeout = 10;
TIME_OUT_TRY(timeout) {
sleep(11);
}
TIME_OUT_CATCH{
TIME_OUT_RETURN(-1);
}
TIME_OUT_END;
return 0;
}
至于为什么用sigsetjmp而不是setjmp:
如果在信号处理函数中调用异常处理,那么这一信号会加入被屏蔽信号集(信号不排队),当用longjmp退出时,影响了原进程的屏蔽信号集!