如果你在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函數,有個問題,為什麼線程内 ,取消 定時器之後能被列印出來?