#include<setjmp.h>
#include<signal.h>
#include<unistd.h>
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
static sigjmp_buf env_alrm;
static volatile sig_atomic_t canjump;
//typedef void (*Sigfunc)(int);
sighandler_t old_handler = NULL;
static void sig_alrm(int signo){
if(canjump == 0){
cout<<"sigsetjmp is not initialized"<<endl;
return;
}
cout<<"sig_alrm starting"<<endl;
canjump = 0;
siglongjmp(env_alrm,1);
}
unsigned int sleep2(unsigned int nesc){
unsigned int pre_alrm;
old_handler= signal(SIGALRM,sig_alrm);
if(old_handler== SIG_ERR)
return nesc;
pre_alrm = alarm(0);
if(sigsetjmp(env_alrm,1)){
if(signal(SIGALRM,old_handler) == SIG_ERR){
cout<<"Restore default func failed"<<endl;
exit(-1);
}
unsigned int tmp = alarm(0);
if(pre_alrm>nesc){
cout<<"Restore alarm default,pre_alrm: "<<pre_alrm<<"\n nesc: "<<nesc<<endl;
return (alarm(pre_alrm-nesc));
}
return tmp;
}
canjump = 1; //Initialize OK
if(pre_alrm)
alarm(pre_alrm<nesc?pre_alrm:nesc);
else
alarm(nesc);
pause();
}
static void sig_alrm_main(int signo){
cout<<"Main alrm starting"<<endl;
}
int main(int argc, char* argv[]){
unsigned int unslept;
if(signal(SIGALRM,sig_alrm_main) == SIG_ERR){
cout<<"Caught ALRM signal ERR"<<endl;
exit(-1);
}
alarm(10);
unslept = sleep2(5);
cout<<"sleep2 returned: "<<unslept<<endl;
sleep(7);
exit(0);
}
/*
在UNIX环境高级编程那本书中,使用setjmp及longjmp;但是使用setjmp及longjmp会导致信号只会接收一次,因为进入第一次进入信号处理函数之后,SIGALRM被加入进程
的信号屏蔽字,同时通过longjmp会跳出信号处理程序,此时SIGALRM仍在信号屏蔽字里,导致无法获取到后续的SIGALRM信号。因此使用专门的sigsetjmp
*/