10

I am having some issues trying to statically link programs using c++0x thread features. Code looks this: (Compiler is gcc 4.6.1 on Debian x86_64 testing)

#include <iostream>
#include <thread>

static void foo() {
  std::cout << "FOO BAR\n";
}

int main() {
  std::thread t(foo);
  t.join();
  return 0;
}

I link it with:

g++ -static -pthread -o t-static t.cpp -std=c++0x

When I execute the program, I have the following error:

terminate called after throwing an instance of 'std::system_error'
  what(): Operation not permitted
Aborted

GDB Debug output looks like this:

Debugger finished
Current directory is ~/testspace/thread/
GNU gdb (GDB) 7.2-debian
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/will/testspace/thread/t-static...done.
(gdb) list -
1   #include <iostream>
(gdb) b 1
Breakpoint 1 at 0x4007c8: file t.cpp, line 1.
(gdb) r
Starting program: /home/will/testspace/thread/t-static 
terminate called after throwing an instance of 'std::system_error'
  what():  Operation not permitted

Program received signal SIGABRT, Aborted.
0x00000000004a8e65 in raise ()
(gdb) bt
#0  0x00000000004a8e65 in raise ()
#1  0x000000000045df90 in abort ()
#2  0x000000000044570d in __gnu_cxx::__verbose_terminate_handler() ()
#3  0x0000000000442fb6 in __cxxabiv1::__terminate(void (*)()) ()
#4  0x0000000000442fe3 in std::terminate() ()
#5  0x0000000000443cbe in __cxa_throw ()
#6  0x0000000000401fe4 in std::__throw_system_error(int) ()
#7  0x00000000004057e7 in std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>) ()
#8  0x0000000000400b18 in std::thread::thread<void (&)()> (this=0x7fffffffe540, __f=@0x4007c4) at /usr/include/c++/4.6/thread:135
#9  0x00000000004007f3 in main () at t.cpp:11
(gdb)

Update:

Linking with static libstdc++ could (possibly) make this error disappear, and the compiled C++0x programs can run on systems without gcc 4.6 libs:

g++ -static-libgcc -pthread -L.-o t thread.cpp -std=c++0x

But first, we should make a symbolic link to 'libstdc++.a' at current directory:

ln -s `g++ -print-file-name=libstdc++.a`

(Reference: http://www.trilithium.com/johan/2005/06/static-libstdc/)

2
  • 2
    My suggestion would be "do not use static linking because the glibc folks will make you suffer eventually". stackoverflow.com/questions/7099712/… Commented Aug 18, 2011 at 5:04
  • 1
    Ran into the same issue with gcc 6.2!!! Imagine that: Not even a warning when linking with -static and -pthread!? You think everything worked out only to run into horrible runtime-exceptions later... Commented Nov 13, 2016 at 19:43

4 Answers 4

7

you can use -u to resolve the problem (test in gcc version 4.6.3/(Ubuntu EGLIBC 2.15-0ubuntu10.4) 2.15 , gcc version 4.8.1/(Ubuntu EGLIBC 2.15-0ubuntu10.5~ppa1) 2.15)

-Wl,-u,pthread_cancel,-u,pthread_cond_broadcast,-u,pthread_cond_destroy,-u,pthread_cond_signal,-u,pthread_cond_wait,-u,pthread_create,-u,pthread_detach,-u,pthread_cond_signal,-u,pthread_equal,-u,pthread_join,-u,pthread_mutex_lock,-u,pthread_mutex_unlock,-u,pthread_once,-u,pthread_setcancelstate

1. reproduce the bug

g++ -g -O0 -static -std=c++11 t.cpp -lpthread
./a.out
terminate called after throwing an instance of 'std::system_error'
  what():  Enable multithreading to use std::thread: Operation not permitted
Aborted (core dumped)


nm a.out | egrep "\bpthread_.*"
                 w pthread_cond_broadcast
                 w pthread_cond_destroy
                 w pthread_cond_signal
                 w pthread_cond_wait
                 w pthread_create
                 w pthread_detach
                 w pthread_equal
                 w pthread_join
                 w pthread_mutex_lock
                 w pthread_mutex_unlock
                 w pthread_once
                 w pthread_setcancelstate

2. resolve the bug

g++ -g -O0 -static -std=c++11 t.cpp -lpthread -Wl,-u,pthread_join,-u,pthread_equal
./a.out  
FOO BAR  


nm a.out | egrep "\bpthread_.*"  
0000000000406320 T pthread_cancel
                 w pthread_cond_broadcast
                 w pthread_cond_destroy
                 w pthread_cond_signal
                 w pthread_cond_wait
0000000000404970 W pthread_create
                 w pthread_detach
00000000004033e0 T pthread_equal
00000000004061a0 T pthread_getspecific
0000000000403270 T pthread_join
0000000000406100 T pthread_key_create
0000000000406160 T pthread_key_delete
00000000004057b0 T pthread_mutex_lock
00000000004059c0 T pthread_mutex_trylock
0000000000406020 T pthread_mutex_unlock
00000000004063b0 T pthread_once
                 w pthread_setcancelstate
0000000000406220 T pthread_setspecific
Sign up to request clarification or add additional context in comments.

2 Comments

Nice, something was missing in another list. This is a really good workaround for those in need of static but without the bulk of -Wl,--whole-archive
This is indeed a nice solution. You can wrap it up as a linker script instead, e.g. libgthread.a and then link with -lgthread instead of -lpthread
6

For reasons exactly unknown to me (I consider this a bug) you can not use std::thread on gcc 4.6 when linking statically, since the function __ghtread_active_p() will be inlined as returning false (look at the assembly of _M_start_thread), causing this exception to be thrown. It might be that they require weak symbols for the pthread_create function there and when statically linking they are not there, but why they don't do it otherwise is beyond me (Note that the assembly later contains things like callq 0x0, there seems to be going something very wrong).

For now I personally use boost::threads since I am using boost anyways...

5 Comments

Thanks for the reply! I have an eclectic solution that statically links libstdc++.a (but not pthread), so that compiled C++0x programs can run on systems without GCC 4.6 libs. Please see my edit above.
It's not true that you can't use GCC's std::thread with static linking, you just have to ensure that your executable contains the relevant symbols from libpthread.a instead of the weak symbols defined by GCC itself. You can do that with -Wl,--whole-archive -lpthread -Wl,--no-whole-archive or using Andy's answer to this question, or a linker script as I commented on Andy's answer. Or for Red Hat, Fedora, CentOS etc. it just works because libpthread.a is built so that it always works.
@JonathanWakely: Note that this is talking about the ancient 4.6 gcc, a lot has changed since then. Even with your proposed linker line, __gthread_active_p() is still inlined to return false on my box.
Works fine for me with 4.6.4 on Debian, either your distro packages gcc or libpthread badly or you're doing it wrong.
The only change relevant to __gthread_active_p since 4.6 is gcc.gnu.org/r188400 which won't make much difference except on Android, or if you're redefining pthread_cancel
5

You should make sure you're linking against pthread library, otherwise you'll get the "Operation not permitted" message.

For instance, to compile your source code, I'd use this:

g++ -Wall -fexceptions  -std=c++0x -g -c file.cpp -o file.o

Then linking with this:

g++ -o file file.o -lpthread

When doing it without object files, you could try something like this:

g++ -Wall -fexceptions -std=c++0x -g main.cpp -o file -lpthread

Remember to leave libraries at the end, since they'll be used on the linking process only.

3 Comments

indeed, it looks like just adding the -lpthread resolves the issue.
In gcc 4.7.1 I noticed that when compiling with a combination of '-pthread' and '-static' the "operation not permitted" error still ocurs. There are 2 workarounds: 1) remove the '-static' or 2) use the "-static-libgcc" + libstdc++.a tip from will above!
The OP is using -pthread which already passes -lpthread to the linker. This answer solves a different problem (the problem of failing to link to libpthread!) not the one described in this question which is about static linking.
2

My previous answer was deleted and I wrote detailed answer.

In common cases this issue happens due incomplete linking of the libpthread. I found information about this here https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52590

You can try link you app with the following flags:

-Wl,--whole-archive -lpthread -Wl,--no-whole-archive

Also you could look at this questions with the similar problem: What is the correct link options to use std::thread in GCC under linux? Starting a std::thread with static linking causes segmentation fault

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.