Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LD_PRELOAD and thread local variable

I have a shared library (libtest.cpp) and a simple program (test.cpp). I want them to share a thread local variable gVar. The shared library is linked through LD_PRELOAD.

Here is my code for the shared library libtest.cpp:

#include<stdio.h>

__thread int gVar;

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

Below is the code for test.cpp.

#include<stdio.h>

__thread int gVar;

void __attribute__((weak)) print_gVar();

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

And I use the following script to compile and run them.

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

The expected result is 10 because the assignment in test.cpp will affect the gVar in libtest.cpp. However, I only got 0. It seems that the the gVar in libtest.cpp and the gVar in test.cpp are not linked.

I did some additional tests:

If I add __attribute__((weak)) to the declaration of gVar in any of the files, the output is still 0.

If I remove __thread from both files, then the result is 10 (successful).

If I add extern and __attribute__((weak)) to the declaration of gVar in libtest.cpp, there will be segmentation fault.

I guess there must be something wrong with LD_PRELOAD and __thread. But I cannot figure out.

Could anyone tell me how I can make it work? Thank you very much!

like image 635
ZillGate Avatar asked Jan 23 '14 23:01

ZillGate


1 Answers

This is not possible, since thread-local-storage requires per-thread initialisation.

LD_PRELOAD will load the library even before the standard library is loaded, which messes up TLS initialisation.

Update:

Please read sections 2 and 3 of ELF Handling For Thread-Local Storage

like image 84
voodooattack Avatar answered Sep 22 '22 04:09

voodooattack