用C模拟异常
/** * @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 <stdio.h>#include <stdlib.h>#include <setjmp.h>#include <signal.h>#include <time.h>#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退出时,影响了原进程的屏蔽信号集!