Static linking with pthreads
Statically-compiling with g for anything with std::threads/pthreads produces code which seg faults either at _start or main.
Using http://wiki.alpinelinux.org/cgi-bin/dl.cgi/v2.5/releases/x86/alpine-2.5.1-x86.iso and qemu, one can set up a minimal system to reproduce the bug.
qemu-system-i386 -enable-kvm -boot d -net nic -net user -cdrom alpine-2.5.1-x86.iso -m 1024 -ctrl-grab
= Inside virtual system, login as root and run the following script ===
#!/bin/sh
- Setup networking and repo locations.
echo “buildbot” >/etc/hostname
echo “http://nl.alpinelinux.org/alpine/v2.5/main/” >> /etc/apk/repositories
echo “auto lo” >/etc/network/interfaces
echo “iface lo inet loopback” >>/etc/network/interfaces
echo “auto eth0” >>/etc/network/interfaces
echo “iface eth0 inet dhcp” >>/etc/network/interfaces
/etc/init.d/networking restart
- Set up the build environment.
apk update
apk add gcc g boost boost-dev make uclibc-dev libiconv-dev
= Minimal test program
localhost:/tmp# cat test.cc
#include
#include
#include
//#include //For sleep_for().
#include <unistd.h>//For sleep().
int main(int argc, char **argv){
std::function<void (void)>func = [](void) ->void {
std::cout << “Hello from func” << std::endl;
};
std::thread tolaunch(func);
tolaunch.detach();
// std::this_thread::sleep_for( std::chrono::seconds(3)); //Produces
compile error unless passed -D_GLIBCXX_USE_NANOSLEEP=1
sleep(3);
return 0;
}
localhost:/tmp# g -std=c++11 -g test.cc
-pthread && ./a.out
Hello from func
localhost:/tmp# g -std=c++11 -g test.cc
-lpthread && ./a.out
Hello from func
localhost:/tmp# g -static -std=c++11 -g
test.cc -pthread && ./a.out
terminate called after throwing an instance of ‘std::system_error’
what(): Operation not permitted
Aborted
localhost:/tmp# g -static -std=c++11 -g
test.cc -lpthread && ./a.out
terminate called after throwing an instance of ‘std::system_error’
what(): Operation not permitted
Aborted
localhost:/tmp#
= Valgrind Output on bad binary = 26745 Memcheck, a memory error detector 26745 Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. 26745 Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info 26745 Command: ./a.out 26745 26745 Conditional jump or move depends on uninitialised value(s) 26745 at 0x809E278: open (in /tmp/a.out) 26745 by 0x809E630: __uClibc_init (in /tmp/a.out) 26745 by 0x809E7B5: __uClibc_main (in /tmp/a.out) 26745 by 0x804855B: _start (in /tmp/a.out) 26745 26745 Conditional jump or move depends on uninitialised value(s) 26745 at 0x809E358: read (in /tmp/a.out) 26745 by 0x809E64E: __uClibc_init (in /tmp/a.out) 26745 by 0x809E7B5: __uClibc_main (in /tmp/a.out) 26745 by 0x804855B: _start (in /tmp/a.out) 26745 26745 Conditional jump or move depends on uninitialised value(s) 26745 at 0x809E208: close (in /tmp/a.out) 26745 by 0x809E658: __uClibc_init (in /tmp/a.out) 26745 by 0x809E7B5: __uClibc_main (in /tmp/a.out) 26745 by 0x804855B: _start (in /tmp/a.out) 26745 26745 Conditional jump or move depends on uninitialised value(s) 26745 at 0x809771E: ioctl (in /tmp/a.out) 26745 by 0x80A0D84: tcgetattr (in /tmp/a.out) 26745 by 0x809C232: isatty (in /tmp/a.out) 26745 by 0x8099B68: _stdio_init (in /tmp/a.out) 26745 by 0x809E6B9: __uClibc_init (in /tmp/a.out) 26745 by 0x809E7B5: __uClibc_main (in /tmp/a.out) 26745 by 0x804855B: _start (in /tmp/a.out) 26745 26745 Conditional jump or move depends on uninitialised value(s) 26745 at 0x809771E: ioctl (in /tmp/a.out) 26745 by 0x80A0D84: tcgetattr (in /tmp/a.out) 26745 by 0x809C232: isatty (in /tmp/a.out) 26745 by 0x8099B81: _stdio_init (in /tmp/a.out) 26745 by 0x809E6B9: __uClibc_init (in /tmp/a.out) 26745 by 0x809E7B5: __uClibc_main (in /tmp/a.out) 26745 by 0x804855B: _start (in /tmp/a.out) 26745 26745 Conditional jump or move depends on uninitialised value(s) 26745 at 0x809E045: __register_atfork (in /tmp/a.out) 26745 by 0x809D078: __malloc_consolidate (in /tmp/a.out) 26745 by 0x8048EB4: _GLOBAL__sub_I_main (test.cc:17) 26745 by 0x809E8D8: __uClibc_main (in /tmp/a.out) 26745 by 0x804855B: _start (in /tmp/a.out) 26745 26745 Conditional jump or move depends on uninitialised value(s) 26745 at 0x809E0DB: __register_atfork (in /tmp/a.out) 26745 by 0x809D078: __malloc_consolidate (in /tmp/a.out) 26745 by 0x8048EB4: _GLOBAL__sub_I_main (test.cc:17) 26745 by 0x809E8D8: __uClibc_main (in /tmp/a.out) 26745 by 0x804855B: _start (in /tmp/a.out) 26745 26745 Conditional jump or move depends on uninitialised value(s) 26745 at 0x804CEE2: __cxa_begin_catch (eh_catch.cc:76) 26745 by 0x804C487: __cxa_throw (eh_throw.cc:82) 26745 by 0x8072B65: std::__throw_system_error(int) (functexcept.cc:106) 26745 by 0x806A579: std::thread::_M_start_thread(std::shared_ptr_Impl_base>) (thread.cc:126) 26745 by 0x80496BF: std::thread::thread&>(std::function&) (thread:133) 26745 by 0x8048913: main (test.cc:11) 26745 26745 Conditional jump or move depends on uninitialised value(s) 26745 at 0x809E2E8: write (in /tmp/a.out) 26745 by 0x809FEF0: __stdio_WRITE (in /tmp/a.out) 26745 by 0x809B923: fwrite_unlocked (in /tmp/a.out) 26745 by 0x809B782: fputs_unlocked (in /tmp/a.out) 26745 by 0x804D007: __cxxabiv1::__terminate(void (*)()) (eh_terminate.cc:40) 26745 by 0x804D044: std::terminate() (eh_terminate.cc:50) 26745 by 0x804C48C: __cxa_throw (eh_throw.cc:83) 26745 by 0x8072B65: std::__throw_system_error(int) (functexcept.cc:106) 26745 by 0x806A579: std::thread::_M_start_thread(std::shared_ptr_Impl_base>) (thread.cc:126) 26745 by 0x80496BF: std::thread::thread&>(std::function&) (thread:133) 26745 by 0x8048913: main (test.cc:11) 26745 terminate called after throwing an instance of 'std::system_error' what(): Operation not permitted26745 Conditional jump or move depends on uninitialised value(s) 26745 at 0x809E2E8: write (in /tmp/a.out) 26745 by 0xD16A407: ??? 26745==
26745 Conditional jump or move depends on uninitialised value(s)
26745 at 0x809E157: raise (in /tmp/a.out)
26745 by 0x804D007: _*cxxabiv1::*_terminate(void (*)())
(eh_terminate.cc:40)
26745 by 0x804D044: std::terminate() (eh_terminate.cc:50)
26745 by 0x804C48C: __cxa_throw (eh_throw.cc:83)
26745 by 0x8072B65: std::__throw_system_error(int)
(functexcept.cc:106)
26745 by 0x806A579:
std::thread::_M_start_thread(std::shared_ptrstd::thread::_Impl_base)
(thread.cc:126)
26745 by 0x80496BF: std::thread::thread<std::function<void
()>&>(std::function<void ()>&) (thread:133)
26745 by 0x8048913: main (test.cc:11)
26745
26745
26745 HEAP SUMMARY:
26745 in use at exit: 0 bytes in 0 blocks
26745 total heap usage: 0 allocs, 0 frees, 0 bytes allocated
26745
26745 All heap blocks were freed — no leaks are possible
26745
26745 For counts of detected and suppressed errors, rerun with: -v
26745 Use —track-origins=yes to see where uninitialised values come
from
26745 ERROR SUMMARY: 15 errors from 11 contexts (suppressed: 0 from 0)
Aborted
===
This is a bit of a slippery bug. I’ve tried quite a few compiler arguments, and the segmentation fault tends to shift around a bit. Sometimes it occurs in __pthreads(..something..something..)_init but I cannot reproduce it atm.
I’m thinking (hoping) this is a user error due to missing devel library, but I’m currently out of ideas.
In the meantime, are there any other alternative thread libraries available in the repo which can replace lpthread ?
(from redmine: issue id 1579, created on 2013-01-18, closed on 2014-04-10)