標籤:inf 清理 線程建立 long read const sig 退出 變數
線上程建立的時候pthread_exit都是調用的固定參數,我們先來看下如果用自動變數作為pthread_exit的參數時出現的問題
typedef struct foo{
int a;
int b;
int c;
int d;
}foo;
void printinfo(const char *s,const struct foo *fp){
printf("%s",s);
printf("structure at 0x%lx\n",(unsigned long)fp);
printf("foo.a=%d\n",fp->a);
printf("foo.b=%d\n",fp->b);
printf("foo.c=%d\n",fp->c);
printf("foo.d=%d\n",fp->d);
}
void printids(const char *s){
pid_t pid;
pthread_t tid;
pid=getpid();
tid=pthread_self();
printf("%s pid %lu tid %lu (0x%lx)\n",s,(unsigned long)pid,(unsigned long)tid,(unsigned long)tid);
}
void *thr_fn2(void *arg){
printf("threaqd 2:ID is %lu\n",(unsigned long)pthread_self());
pthread_exit((void *)0);
}
void *thr_fn1(void *arg){
foo f={1,2,3,4};
printinfo("thread1:\n",&f);
pthread_exit((void *)&f);
}
int main()
{
pthread_t tid1,tid2;
foo *fp;
pthread_create(&tid1,NULL,thr_fn1,NULL);
pthread_join(tid1,(void *)&fp);
Sleep(1);
printf("parent starting create thread2:\n");
pthread_create(&tid2,NULL,thr_fn2,NULL);
Sleep(1);
printinfo("parent:\n",fp);
return 0;
}
在這個程式中,調用pthread_join(tid1,(void *)&fp)的時候會將返回碼賦值給fp參數。然後再父進程中調用fp。
執行結果:可以看到當父進程中試圖訪問已退出的第一個線程傳給它的結構時,記憶體不在有效,因此得到了SIGSEGV訊號
Thread1:
Structure at 0x2bfff04
foo.a=1
foo.b=2
foo.c=3
foo.d=4
parent starting create thread2
thread 2 : ID is 3
segmentation fault(core dumped)
線程可以俺怕它退出時需要調用的函數,這樣的函數稱為線程清理處理常式。
void thread_cleanup_push(void (*rtn)(void *), void *arg);
void pthread_cleanup_pop(int execute)
rtn是調用的函數,arg是傳入的參數。
void cleanup(void *arg){
printf("cleanup:%s\n",(char *)arg);
}
void *thr_fn2(void *arg){
printf("thread2 start\n");
pthread_cleanup_push(cleanup,"thread2 first handler");
pthread_cleanup_push(cleanup,"thread2 second handler");
printf("thread2 push complete\n");
if (arg)
pthread_exit((void *)2);
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
}
void *thr_fn1(void *arg){
printf("thread1 start\n");
pthread_cleanup_push(cleanup,"thread1 first handler");
pthread_cleanup_push(cleanup,"thread1 second handler");
printf("thread1 push complete\n");
if (arg)
return((void *)1);
pthread_cleanup_pop(0);
pthread_cleanup_pop(0);
}
int main()
{
pthread_t tid1,tid2;
void *tret;
pthread_create(&tid1,NULL,thr_fn1,(void *)1);
pthread_create(&tid2,NULL,thr_fn2,(void *)1);
pthread_join(tid1,&tret);
printf("thread 1 exit code %ld\n",(long)tret);
pthread_join(tid2,&tret);
printf("thread 2 exit code %ld\n",(long)tret);
return 0;
}
運行結果如下:兩個線程都正確的自動啟動和退出了,但是只有第二個線程的清理處理常式被調用了,如果線程是通過從它的啟動曆程中返回(return)而不是pthread_exit的話,它的清理程式就不會調用
linux c編程:線程退出