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/)

will
  • 589
  • 1
  • 7
  • 15
  • 2
    My suggestion would be "do not use static linking because the glibc folks will make you suffer eventually". http://stackoverflow.com/questions/7099712/whats-the-accepted-method-for-deploying-a-linux-application-that-relies-on-share/7101577#7101577 – Nemo Aug 18 '11 at 05:04
  • 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... – Julian Nov 13 '16 at 19:43

4 Answers4

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
Andy
  • 337
  • 3
  • 3
  • 1
    Nice, something was missing in [another list](https://bugs.alpinelinux.org/issues/1579#note-5). This is a really good workaround for those in need of static but without the bulk of [-Wl,--whole-archive](http://stackoverflow.com/a/28864400/673826) – mlt Jun 08 '15 at 23:08
  • This is indeed a nice solution. You can wrap it up as a linker script instead, e.g. [libgthread.a](https://gist.github.com/jwakely/84e905daa67a4c06f3e6) and then link with `-lgthread` instead of `-lpthread` – Jonathan Wakely Jul 07 '15 at 10:27
6

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.

  • indeed, it looks like just adding the -lpthread resolves the issue. – Klaas van Gend Oct 16 '12 at 13:01
  • 4
    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! – Filipe Felisbino Dec 13 '12 at 16:32
  • 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. – Jonathan Wakely Jul 07 '15 at 10:31
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...

PlasmaHH
  • 15,673
  • 5
  • 44
  • 57
  • 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. – will Aug 18 '11 at 04:13
  • 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. – Jonathan Wakely Jul 07 '15 at 10:26
  • @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. – PlasmaHH Jul 07 '15 at 10:38
  • Works fine for me with 4.6.4 on Debian, either your distro packages gcc or libpthread badly or you're doing it wrong. – Jonathan Wakely Jul 07 '15 at 11:53
  • The only change relevant to __gthread_active_p since 4.6 is https://gcc.gnu.org/r188400 which won't make much difference except on Android, or if you're redefining `pthread_cancel` – Jonathan Wakely Jul 07 '15 at 11:58
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

Community
  • 1
  • 1
Denis Zaikin
  • 569
  • 4
  • 10