这是我的情况的描述:我必须照顾产品中的错误。线程创建为joinable
,它必须完成工作,终止并没有人会要求pthread_join()
它。因此,该线程是使用JOINABLE属性创建的(默认情况下),并且在终止之前调用下一个代码:
{ pthread_detach(pthread_self()); pthread_exit(NULL); }
在我遇到的所有32位Linux发行版上,它都像是一种魅力,但SIGSEGV
在64位发行版上却引起了(Ubuntu 13.04 x86_64和Debian)。我没有尝试使用Slackware。这是一个核心:
Core was generated by `IsaVM -s=1 -PrjPath="/home/taf/Linux_Fov_540148/Cmds" -stgMode=1 -PR -Failover'.
Program terminated with signal 11, Segmentation fault.
#0 0x00007f5911a7c009 in pthread_detach () from /lib/x86_64-linux-gnu/libpthread.so.0
(gdb) bt
#0 0x00007f5911a7c009 in pthread_detach () from /lib/x86_64-linux-gnu/libpthread.so.0
#1 0x000000000041310d in _kerCltDownloadThr (StartParams=0x6bfce0 <RESFOV>) at ./dker0clt.c:1258
#2 0x00007f5911a7ae9a in start_thread () from /lib/x86_64-linux-gnu/libpthread.so.0
#3 0x00007f591159f3fd in clone () from /lib/x86_64-linux-gnu/libc.so.6
#4 0x0000000000000000 in ?? ()
我想出了解决此错误的方法-pthread_attr_setdetachstate()
在创建线程之前,我为线程设置了CREATE_DETACHABLE属性(使用),并且该线程可以按预期工作。
但是我的问题是-调用此代码是否构成犯罪?
{ pthread_detach(pthread_self()); pthread_exit(NULL); }
pthread_detach()
通话后是否会异步执行某些操作并导致pthread_exit()
出现问题?但是崩溃点pthread_detach()
不是pthread_exit()
!我完全不了解这次崩溃的原因!为什么要在32位上工作?在pthread
实施过程中是否存在竞争条件?
pthread_join()
不要求此线程。
预先感谢您的任何想法。
我用受人尊敬的@MaximYegorushkin提供的方法完成了研究。AddressSanitizer
向我展示了我们产品中的一个缓冲区obverflow,但这与我的问题无关(我以后肯定会修复它,拥有这样一个明智的工具来寻找bug总是很好的)。因此决定pthread_xxx
用LD_PRELOAD
方法覆盖所有必要的功能。我运行一个简单的测试以确保我的库能按预期工作:
[HACK] Loading pthread hack.
Starting thread...!
[HACK] pthread_create: thread=7FAC6C86D700
Waiting for 2 seconds...
[HACK] pthread_self: thread=7FAC6C86D700
thread_func: thread id = 7FAC6C86D700
Thread: sin(3.26) = -0.121109
[HACK] pthread_self: thread=7FAC6C86D700
[HACK] pthread_detach: thread=7FAC6C86D700
Terminating...
[HACK]开头的所有字符串都是由我的threadhack.so
库生成的。然后,我使用该库运行我的项目,它为我指明了问题所在:
执行的代码: { pthread_detach(pthread_self()); pthread_exit(NULL); }
调试痕迹:
[HACK] pthread_create: thread=7F403251CB00
.....
[HACK] pthread_self: thread=7F403251CB00
[HACK] pthread_detach: thread=3251CB00
因此,我们看到它pthread_self
返回了一个好的线程ID,但pthread_detach
收到的它已经被篡改(切成32位)。怎么会这样 我为我的简单工作测试应用程序和项目生成了汇编代码:
参考应用:
call pthread_self
movq %rax, %rdi
call pthread_detach
movl $0, %edi
call pthread_exit
因此,我们在这里看到该movq
指令用于复制64位线程ID(movq %rax, %rdi
)。OK,检查为我的项目生成了什么GCC :
movl $0, %eax
call pthread_self
movl %eax, %edi
movl $0, %eax
call pthread_detach
movl $0, %edi
movl $0, %eax
call pthread_exit
哇!我们有两条movl
指令(32位),一条复制最低有效的32位(movl %eax, %edi
),而不是最高有效部分总是将其置零!(movl $0, %eax
)。因此,这是损坏了thead id的原因。我不知道为什么代码如此不同-编译标志相同。我GCC 4.7
在GCC 4.8
(最新的软件包中Ubuntu 13.10 x86_64
)看到了这个错误。
所以至少现在我明白了。感谢@Maxim和出色的工具。我又学了新东西。
PS:我不知道如何向GCC团队提交错误报告。我无法在一个简单的小型应用程序上重现该问题,也无法将其交给我的项目,因为它是专有软件,因此我接受了NDA的许可,不予分发。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句