LD_PRELOAD 和线程局部变量

Posted

技术标签:

【中文标题】LD_PRELOAD 和线程局部变量【英文标题】:LD_PRELOAD and thread local variable 【发布时间】:2014-01-23 23:40:00 【问题描述】:

我有一个共享库 (libtest.cpp) 和一个简单的程序 (test.cpp)。我希望他们共享一个线程局部变量 gVar。共享库通过 LD_PRELOAD 链接。

这是我的共享库 libtest.cpp 的代码:

#include<stdio.h>

__thread int gVar;

void print_gVar()
  printf("%d\n", gVar);

下面是 test.cpp 的代码。

#include<stdio.h>

__thread int gVar;

void __attribute__((weak)) print_gVar();

int main()
  gVar = 10;
  print_gVar(); 
  return 0;

我使用下面的脚本来编译和运行它们。

g++ -g -shared -fPIC -olibtest.so libtest.cpp
g++ -g -fPIC -o test test.cpp
LD_PRELOAD=./libtest.so ./test

预期结果为 10,因为 test.cpp 中的赋值会影响 libtest.cpp 中的 gVar。但是,我只得到了0。似乎libtest.cpp中的gVar和test.cpp中的gVar没有链接。

我做了一些额外的测试:

如果我在任何文件中将__attribute__((weak)) 添加到gVar 的声明中,输出仍然是0。

如果我从两个文件中删除 __thread,则结果为 10(成功)。

如果我在libtest.cpp中gVar的声明中添加extern__attribute__((weak)),就会出现分段错误。

我猜LD_PRELOAD__thread 一定有问题。但我想不通。

谁能告诉我如何让它工作?非常感谢!

【问题讨论】:

【参考方案1】:

这是不可能的,因为线程本地存储需要每个线程初始化。

LD_PRELOAD 甚至会在加载标准库之前加载该库,这会打乱 TLS 初始化。

更新:

请阅读ELF Handling For Thread-Local Storage的第2和3部分

【讨论】:

非常感谢!你能再给我一些参考吗? 不客气,刚刚添加。遗憾的是,没有提到这个问题的具体内容,但您首先应该对 TLS 初始化的工作原理有一个很好的了解。 @voodooattack 我不太明白你的回答。你能详细说明为什么它不起作用吗?另外,您是否暗示 LD_PRELOADed 库不能使用 tls?这对我来说听起来不正确。很多场景都需要使用 LD_PRELOADed 库和 tls,对吧?例如,github.com/jemalloc/jemalloc/issues/937

以上是关于LD_PRELOAD 和线程局部变量的主要内容,如果未能解决你的问题,请参考以下文章

线程局部存储主要用来干啥的?

java 局部静态变量在多线程环境下是不是有线程安全问题??

线程局部变量

线程局部存储的Win32实现

什么是线程局部变量?

什么是线程局部变量?