Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++0x thread static linking problem

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

like image 593
will Avatar asked Aug 17 '11 09:08

will


3 Answers

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
like image 61
Andy Avatar answered Oct 24 '22 20:10

Andy


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.

like image 41
Alexandre Schmidt Avatar answered Oct 24 '22 21:10

Alexandre Schmidt


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...

like image 40
PlasmaHH Avatar answered Oct 24 '22 22:10

PlasmaHH