APUE2勘误-11.5节 线程终止(关于线程清理处理程序)

平台:Linux 2.6.28-19-generic

书中讲解所用的linux版本为Linux 2.4.22,我没有在此版本上做实验的机会,只是在当前用的版本上做了测试,问题原因可能是Linux内核版本升级导致对线程终止的处理方式进行了改动。

代码如下:

 1 #include "apue.h"
2 #include <pthread.h>
3
4 void
5 cleanup(void *arg)
6 {
7 printf("cleanup: %s\n", (char *)arg);
8 }
9
10 void *
11 thr_fn1(void *arg)
12 {
13 printf("thread 1 start\n");
14 pthread_cleanup_push(cleanup, (void*)"thread 1 first handler");
15 pthread_cleanup_push(cleanup, (void*)"thread 1 second handler");
16 printf("thread 1 push complete\n");
17 if (arg)
18 return((void *)1);
19 pthread_cleanup_pop(0);
20 pthread_cleanup_pop(0);
21 return((void *)1);
22 }
23
24 void *
25 thr_fn2(void *arg)
26 {
27 printf("thread 2 start\n");
28 pthread_cleanup_push(cleanup, (void*)"thread 2 first handler");
29 pthread_cleanup_push(cleanup, (void*)"thread 2 second handler");
30 printf("thread 2 push complete\n");
31 if (arg)
32 pthread_exit((void *)2);
33 pthread_cleanup_pop(0);
34 pthread_cleanup_pop(0);
35 pthread_exit((void *)2);
36 }
37
38 int
39 main(void)
40 {
41 int err;
42 pthread_t tid1, tid2;
43 void *tret;
44
45 err = pthread_create(&tid1, NULL, thr_fn1, (void *)1);
46 if (err != 0)
47 err_quit("can't create thread 1: %s\n", strerror(err));
48 err = pthread_create(&tid2, NULL, thr_fn2, (void *)1);
49 if (err != 0)
50 err_quit("can't create thread 2: %s\n", strerror(err));
51 err = pthread_join(tid1, &tret);
52 if (err != 0)
53 err_quit("can't join with thread 1: %s\n", strerror(err));
54 printf("thread 1 exit code %d\n", (int)tret);
55 err = pthread_join(tid2, &tret);
56 if (err != 0)
57 err_quit("can't join with thread 2: %s\n", strerror(err));
58 printf("thread 2 exit code %d\n", (int)tret);
59 exit(0);
60 }

程序运行结果:

 1 thread 1 start
2 thread 1 push complete
3 cleanup: thread 1 second handler
4 cleanup: thread 1 first handler
5 thread 2 start
6 thread 2 push complete
7 cleanup: thread 2 second handler
8 cleanup: thread 2 first handler
9 thread 1 exit code 1
10 thread 2 exit code 2

在原书中提到,

当线程执行以下动作时调用清理函数,

1.调用pthread_exit时;

2.响应取消请求时;

3.用非零execute函数调用pthread_cleanup_pop时。

注意,并不包括线程执行return函数,对应的在原书中给出的编程结果,没有程序运行结果中给出的第3、4行,也即线程1的线程清理函数是没有被执行的。但实际运行情况是,在Linux 2.6版本中,线程执行函数通过return返回,也会执行线程清理。

因此,需要对线程清理函数的触发条件,以及对应的执行结果作相应的update。

现在还有一个疑问:

线程执行环境中调用return返回和调用pthread_exit返回有什么区别吗?(return本身也要求将返回值显示转换成void*)

原文地址:https://www.cnblogs.com/liuhao/p/2238333.html