On Mon, Sep 23, 2013 at 02:08:03PM +0200, Matthias Klose wrote: > With binutils from the 2.24 branch or trunk, the behaviour of --as-needed did > change, and what worked with binutils 2.23, now fails with 2.24: > > $ cat thread.cpp > #include <thread> > > void factorial(int n, unsigned long long int *result) { > if (n==1) { > *result=1; > return; > } > *result=1; > for (; n!=0; n--) *result=*result*n; > } > > int main() { > unsigned long long int a; > unsigned long long int *c=&a; > std::thread t1(factorial,15,c); > t1.join(); > return 0; > } > $ ld --version > GNU ld (GNU Binutils for Ubuntu) 2.23.2 > $ g++ -Wl,--as-needed -pthread thread.cpp -std=c++11 -o thread && ./thread > > $ ld --version > GNU ld (GNU Binutils for Debian) 2.23.52.20130828 > $ g++ -Wl,--as-needed -pthread thread.cpp -std=c++11 -o thread && ./thread > terminate called after throwing an instance of 'std::system_error' > what(): Enable multithreading to use std::thread: Operation not permitted > Aborted > > So the test program doesn't have any direct references to symbols in > libpthread, > and isn't linked, and fails to run. > > According to the binutils maintainers, this behaviour is expected: > > https://sourceware.org/ml/binutils/2013-08/msg00286.html > https://sourceware.org/ml/binutils/2013-09/msg00000.html > > but it seems a bit odd that g++ -Wl,--as-needed -pthread isn't working > anymore.
Try compiling that testcase with -static rather than -Wl,--as-needed. You'll hit std::system_error just like you do here. I believe that is a libstdc++ bug, and can be solved by making libstdc++.a use strong references to pthread symbols from std::thread::join() (and perhaps other objects that provide c++ thread support, if there are such). libstdc++.a objects that are just testing "is this program threaded" should continue to use weak references. Solving the problem with --as-needed and libstdc++.so isn't so easy. One solution might be to split off thread support from libstdc++.so.6. Otherwise we'd need to solve the transitive reference somehow. ie. Teach the linker that a reference to std::thread::join() means that pthread_create is required. One obvious way to do that is have the compiler reference pthread_create in objects that use std::thread::join(). -- Alan Modra Australia Development Lab, IBM