Bug 52590 - std::thread Segmentation fault static linking
Summary: std::thread Segmentation fault static linking
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: libstdc++ (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
: 94009 (view as bug list)
Depends on:
Blocks:
 
Reported: 2012-03-14 20:38 UTC by Jason Toffaletti
Modified: 2023-03-03 19:10 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jason Toffaletti 2012-03-14 20:38:44 UTC
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.7.0~rc1-1ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-4.7/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++,go --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.7.0 20120302 (prerelease) (Ubuntu/Linaro 4.7.0~rc1-1ubuntu1) 

$ g++ -static -pthread -std=c++0x -o thread thread.cc 

$ ./thread 
pthread_create works
std::thread works
Segmentation fault

$ cat thread.cc 
#include <thread>
#include <iostream>

void *foo1(void *) {
    std::cout << "pthread_create works\n";
    return 0;
}

void foo2() {
    std::cout << "std::thread works\n";
}

int main() {
    {
        pthread_t t;
        pthread_create(&t, 0, foo1, 0);
        void *r;
        pthread_join(t, &r);
    }

    {
        std::thread t(foo2);
        t.join();
    }
    return 0;
}

I was surprised to see that pthreads worked in this case while std::thread did not. I've also heard that boost::thread works. I'm having a hard time finding any documentation on whether static linking and std::thread should work together. Also see http://stackoverflow.com/questions/7090623/c0x-thread-static-linking-problem

If it is the case that pthreads and std::thread cannot work together with static linking, then it'd be nice to fail at some point before runtime if that is possible.
Comment 1 Andrew Pinski 2012-03-14 20:42:22 UTC
> -static 

You need to make sure all of libpthread.a is included, right it does not get linked that way.

This is not a GCC or glibc bug.
Comment 2 Jason Toffaletti 2012-03-14 21:29:18 UTC
(In reply to comment #1)
> > -static 
> 
> You need to make sure all of libpthread.a is included, right it does not get
> linked that way.
> 
> This is not a GCC or glibc bug.

Your comment seems to suggest there is a way, but I can't find it.

g++ -Wl,--whole-archive -static -pthread -std=c++0x -o thread thread.cc

Gives pages of linker errors. http://sourceware.org/bugzilla/show_bug.cgi?id=10652 suggests glibc and pthreads just don't work with static linking.
Comment 3 Jason Toffaletti 2012-03-15 04:14:40 UTC
$ g++-4.7 -Wl,-M -v -static -pthread -std=c++0x -o thread thread.cc shows all of libpthread being linked.

With a bit more digging I traced the problem to /usr/include/c++/4.7.0/x86_64-linux-gnu/bits/gthr-posix.h declaring all of its symbols with __attribute__((weakref)) even when linking statically. Which caused the __gthread_* symbols to resolve to zero. I found this for some background info http://gcc.gnu.org/ml/gcc/2005-10/msg00235.html

This change made my example work:

$ g++ -D_GLIBCXX_GTHREAD_USE_WEAK=0 -static -pthread -std=c++0x -o thread thread.cc 
$ ./thread 
pthread_create works
std::thread works

However, if I change the code to call std::thread::detach instead of join, then it crashes again with std::thread::detach being resolved to zero.

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0  0x0000000000000000 in ?? ()
#1  0x0000000000439785 in std::thread::detach() ()
#2  0x0000000000401f52 in main ()
Comment 4 Jakub Jelinek 2012-03-15 07:46:27 UTC
The weakref attributes are of course correct, the bug is that you aren't linking the whole libpthread.a into the app.  On some Linux distributions libpthread.a
has all the objects linked together with ld -r and therefore this will just work there, on others you need -Wl,--whole-archive -lpthread -Wl,--no-whole-archive.
Better yet don't link statically, there are many reasons why it is a bad idea.
http://www.akkadia.org/drepper/no_static_linking.html
Comment 5 Andrew Pinski 2020-03-03 03:31:29 UTC
*** Bug 94009 has been marked as a duplicate of this bug. ***
Comment 6 Jonathan Wakely 2022-03-09 17:40:02 UTC
*** Bug 104852 has been marked as a duplicate of this bug. ***
Comment 7 GCC Commits 2023-03-03 19:10:35 UTC
The master branch has been updated by Alexandre Oliva <aoliva@gcc.gnu.org>:

https://gcc.gnu.org/g:21edd841611a97442a6b95e8ec7e91ff8fd3a451

commit r13-6461-g21edd841611a97442a6b95e8ec7e91ff8fd3a451
Author: Alexandre Oliva <oliva@adacore.com>
Date:   Fri Mar 3 15:59:36 2023 -0300

    link pthread_join from std::thread ctor
    
    Like pthread_create, pthread_join may fail to be statically linked in
    absent strong uses, so add to user code strong references to both when
    std::thread objects are created.
    
    
    for  libstdc++-v3/ChangeLog
    
            PR libstdc++/104852
            PR libstdc++/95989
            PR libstdc++/52590
            * include/bits/std_thread.h (thread::_M_thread_deps): New
            static implicitly-inline member function.
            (std::thread template ctor): Pass it to _M_start_thread.
            * src/c++11/thread.cc (thread::_M_start_thread): Name depend
            parameter, force it live on entry.