当“正确”链接(进一步解释)时,下面的两个函数调用都会在 pthread 调用实现时无限期阻塞,cv.notify_one
并且cv.wait_for
:
// let's call it odr.cpp, which forms libodr.so
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
void Notify() {
std::chrono::milliseconds(100);
std::unique_lock<std::mutex> lock(mtx);
ready = true;
cv.notify_one();
}
void Get() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait_for(lock, std::chrono::milliseconds(300));
}
当上述共享库用于以下应用程序时:
// let's call it test.cpp, which forms a.out
int main() {
std::thread thr([&]() {
std::cout << "Notify\n";
Notify();
});
std::cout << "Before Get\n";
Get();
std::cout << "After Get\n";
thr.join();
}
问题仅在链接时重现libodr.so
:
- 与 g++
- 带黄金链接器
-lpthread
作为依赖提供
使用以下版本的相关工具:
Linux Mint 18.3 Sylvia
binutils 2.26.1-1ubuntu1~16.04.6
g++ 4:5.3.1-1ubuntu1
libc6:amd64 2.23-0ubuntu10
所以我们最终得到:
__pthread_key_create
在 PLT 中定义为 WEAK 符号- 没有
libpthread.so
作为 ELF 中的依赖项
如此处所示:
$ g++ -fPIC -shared -o build/libodr.so build/odr.cpp.o -fuse-ld=gold -lpthread && readelf -d build/libodr.so | grep Shared && readelf -Ws build/libodr.so | grep -m1 __pthread_key_create
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
10: 0000000000000000 0 FUNC WEAK DEFAULT UND __pthread_key_create
另一方面,对于以下任何一种情况,我们都不会遇到错误:
- 铿锵++
- bfd 链接器
- 没有明确的
-lpthread
-lpthread
但与-Wl,--no-as-needed
注意:这次我们有:
NOTYPE
并且没有libpthread.so
依赖WEAK
和libpthread.so
依赖
如此处所示:
$ clang++ -fPIC -shared -o build/libodr.so build/odr.cpp.o -fuse-ld=gold -lpthread && readelf -d build/libodr.so | grep Shared && readelf -Ws build/libodr.so | grep -m1 __pthread_key_create && ./a.out
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
24: 0000000000000000 0 FUNC WEAK DEFAULT UND __pthread_key_create@GLIBC_2.2.5 (7)
$ g++ -fPIC -shared -o build/libodr.so build/odr.cpp.o -fuse-ld=bfd -lpthread && readelf -d build/libodr.so | grep Shared && readelf -Ws build/libodr.so | grep -m1 __pthread_key_create && ./a.out
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
14: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __pthread_key_create
$ g++ -fPIC -shared -o build/libodr.so build/odr.cpp.o -fuse-ld=gold && readelf -d build/libodr.so | grep Shared && readelf -Ws build/libodr.so | grep -m1 __pthread_key_create && ./a.out 0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
18: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __pthread_key_create
$ g++ -fPIC -shared -o build/libodr.so build/odr.cpp.o -fuse-ld=gold -Wl,--no-as-needed -lpthread && readelf -d build/libodr.so | grep Shared && readelf -Ws build/libodr.so | grep -m1 __pthread_key_create && ./a.out
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libstdc++.so.6]
0x0000000000000001 (NEEDED) Shared library: [libm.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
10: 0000000000000000 0 FUNC WEAK DEFAULT UND __pthread_key_create@GLIBC_2.2.5 (4)
可以在这里找到编译/运行的完整示例:https ://github.com/aurzenligl/study/tree/master/cpp-pthread
什么时候使用 pthread 破坏 shlib并且在 ELF 中找不到依赖项__pthread_key_create
?动态链接器是否从(stubs) 获取 pthread 符号而不是?WEAK
libpthread.so
libc.so
libpthread.so