在POSIX线程API中提供了一个pthread_cleanup_push()/pthread_cleanup_pop()函数对用于自动释放资源 --从pthread_cleanup_push()的调用点到pthread_cleanup_pop()之间的程序段中的终止动作(包括调用 pthread_exit()和取消点终止)都将执行pthread_cleanup_push()所指定的清理函数。API定义如下:
void pthread_cleanup_push(void (*routine) (void *), void *arg)
void pthread_cleanup_pop(int execute)
pthread_cleanup_push()/pthread_cleanup_pop()采用先入后出的栈结构管理,void routine(void *arg)函数在调用pthread_cleanup_push()时压入清理函数栈,多次对pthread_cleanup_push()的调用将在清理函数栈中形成一个函数链,在执行该函数链时按照压栈的相反顺序弹出。execute参数表示执行到pthread_cleanup_pop()时是否在弹出清理函数的同时执行该函数,为0表示不执行,非0为执行;这个参数并不影响异常终止时清理函数的执行。
但有一点必须注意,在pthread_cleanup_push和pthread_mutex_lock之间不能有退出点,pthread_mutex_unlock 和pthread_cleanup_pop之间不能有退出点,否则会导致重复解锁引起段错误。
示例程序如下:
#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
int fd;
char buf[40];
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
void unlockmutex(void *args)
{
pthread_mutex_unlock((pthread_mutex_t*)args);
}
void *search(void *arg)
{
unsigned int d=0;
pthread_cleanup_push(unlockmutex, &mutex);
pthread_mutex_lock(&mutex);
for(;d >= 0;d++)
{
printf("d=%d\n",d);
}
pthread_mutex_unlock(&mutex);
pthread_cleanup_pop(0);
}
int main()
{
pthread_t tid;
pthread_create(&tid,NULL,search,NULL);
pthread_detach(tid);
usleep(1);
pthread_cancel(tid);
printf("the main end\n");
//usleep(1);
//pthread_join(tid,NULL);
pthread_mutex_lock(&mutex); //加了pthread_cleanup_push(unlockmutex, &mutex) 和 pthread_cleanup_pop(0) 后,主线程能正常得到锁退出,否则不能得到锁。
printf("the cancel prom is over\n");
pthread_mutex_unlock(&mutex);
}