踩坑之路-线程私有数据

背景介绍

  • 进程A
  • 进程B
动态链接库

c.so -----------我们模块的so
d.so
e.so
进程A会加载c.so、d.so
进程B会加载c.so、d.so、e.so

启动d.so 和e.so的构造函数中均会创建线程私有数据
进程A每次重启时,会产生core文件,产生core的位置在c.so
进程B不会出core文件。

定位过程

发现进程A出core的地方是c.so中的私有数据,发现私有数据是乱的,怀疑是初始化时有问题。

查看代码发现函数初始化私有数据时调用pthread_getspecific(0)查看是否已经有配置,如果没有则创建私有数据

进程A调用pthread_getspecific(0)不为空,进程B调用pthread_getspecific(0)为空。

这就比较奇怪了,相同的代码,为什么结果不一样呢?想了好久,只有可能进程启动过程中已有的流程导致的,就试着把线程私有数据的各个函数(pthread_key_create、pthread_key_delete、pthread_setspecific、pthread_getspecific)均断住后启动进程。
(由于不知道是私有数据创建有问题,还是创建后又删除了,就用了这个笨办法,后来想如果先看看源码就好了,能帮助清理下思路)

启动过程中发现进程A和B启动过程果然不一样
首先加载的so不一样,进程B先加载e.so,然后是d.so;进程A先加载d.so。
更特别的是进程B第一次调用pthread_key_create创建线程私有数据的key后,没有调用pthread_setspecific设置线程私有数据。
而进程A第一次调用pthread_key_create创建线程私有数据的key后,接着调用pthread_setspecific设置线程私有数据。
猜测是进程A获取私有数据是正好是d.so中设置的私有数据,不为NULL,进程B中获取的是e.so中的私有数据,而e.so的私有数据没有设置,正好获取的是NULL。

由于都是release的.so,没办法看出来各个值是多少,只能通过查看cpu寄存器中key的入参和出参变化来验证猜想。发现第一个设置私有数据的key,key的入参和出参均是0;第二个设置私有数据时,key的入参是0,出参是1。

直接看源码,果然如此。

e.so创建了私有数据Key,没设置私有数据,创建的私有数据Key正好为0,我们模块获取私有数据的Key正好是0,获取私有数据为NULL,无巧不成书,就这么巧合的导致了进程A有问题,进程B没有问题。

源码

创建私有数据Key

key的分配是直接从0开始,一直向后找第一个未使用的值。

int pthread_key_create(pthread_key_t * key, destr_function destr)
{
   
  int i;

  __pthread_mutex_lock(&pthread_keys_mutex);
  
  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值