g++ -Wl,--as-needed -pthread behaviour

Alan Modra amodra@gmail.com
Tue Sep 24 01:22:00 GMT 2013


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



More information about the Gcc mailing list