如果你在sigsetjmp条件内构造了一个对象,那么很容易造成内存泄露,程序的
突然跳转,导致析构函数还没有执行.以下是测试代码
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <setjmp.h>
#include <signal.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <pthread.h>
class A{
public:
A(){
i=0;
printf("constructor\n");
}
~A(){
printf("unconstructor\n");
}
int i;
};
pthread_t tid_result_manager;
jmp_buf jb_result_manager;
void sigexit_main(int)
{
printf("主线程接收到了退出信号。\n" );
pthread_kill( tid_result_manager,SIGUSR1 );
return;
}
void sigalrm(int s) {
printf("sigalrm signal=%d\n",s);
siglongjmp( jb_result_manager, 1 ); //此处返回1 ,继续执行
}
void sigexit(int s) {
printf("sigexit signal=%d\n",s);
pthread_t tid = pthread_self();
if ( tid == tid_result_manager )
siglongjmp( jb_result_manager, -1 ); //返回-1
assert(0);
}
int icout=0;
void *result_manager( void * )
{
sigset_t set;
int alarm_time = 2;
int ret=0;
printf("线程启动。\n" );
signal( SIGUSR1, sigexit );
signal( SIGALRM, sigalrm );
sigemptyset( &set );
sigaddset( &set, SIGUSR1 );
sigaddset( &set, SIGALRM );
pthread_sigmask( SIG_UNBLOCK, &set, NULL ); //不阻止SIGUSR1信号
if ( ( ret = sigsetjmp( jb_result_manager, 1 ) ) != -1 ) {
if ( ret ) {
printf("ret=%d,alarm_time=%d\n",ret,alarm_time);
pthread_sigmask( SIG_BLOCK, &set, NULL );
icout++;
if(icout<5)
{
alarm( alarm_time );
}
A a;
a.i++;
printf("cccc a.i=%d\n",a.i);
sleep(5);
alarm(0); //取消定时器
printf("线程内 ,取消 定时器之后 \n");
pthread_sigmask( SIG_UNBLOCK, &set, NULL );
// while ( 1 ) pause(); //让程序等待信号
}
printf("waiting signal。\n" );
while ( 1 ) pause(); //让程序等待信号
}
printf("线程退出。\n" );
return NULL;
}
int main( int argc, char *argv[] )
{
printf("pid=%d",getpid());
sigset_t set;
sigfillset( &set );
sigprocmask( SIG_BLOCK, &set, NULL );
pthread_create( &tid_result_manager, NULL, result_manager, NULL );
signal( SIGINT, sigexit_main );
signal( SIGTERM, sigexit_main );
signal( SIGQUIT, sigexit_main );
sigemptyset( &set );
sigaddset( &set, SIGINT );
sigaddset( &set, SIGTERM );
sigaddset( &set, SIGQUIT );
pthread_sigmask( SIG_UNBLOCK, &set, NULL );
sleep(5);
pthread_kill( tid_result_manager, SIGALRM );
printf("SIGALRM sigal sended\n");
pthread_join( tid_result_manager, NULL );
printf("program退出。\n" );
return 0;
}
打印结果为
pid=5487线程启动。
waiting signal。
SIGALRM sigal sended
sigalrm signal=14
ret=1,alarm_time=2
constructor
cccc a.i=1
线程内 ,取消 定时器之后
sigalrm signal=14
ret=1,alarm_time=2
constructor
cccc a.i=1
线程内 ,取消 定时器之后
sigalrm signal=14
ret=1,alarm_time=2
constructor
cccc a.i=1
线程内 ,取消 定时器之后
sigalrm signal=14
ret=1,alarm_time=2
constructor
cccc a.i=1
线程内 ,取消 定时器之后
sigalrm signal=14
ret=1,alarm_time=2
constructor
cccc a.i=1
线程内 ,取消 定时器之后
unconstructor
waiting signal。
主线程接收到了退出信号。
sigexit signal=10
线程退出。
program退出。
可以很明显的看到析构函数就执行了最后一次,所以使用时一定要小心.尽可能少使用sigsetjmp siglongjmp函数,有个问题,为什么线程内 ,取消 定时器之后能被打印出来?