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*)
分类:
Linux编程
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库