When G++ Static Link Pthread, Cause Segmentation Fault, Why

Why does linking with pthread cause a segmentation fault?

It turns out it was the GCC compiler or libstdc++ that is buggy/broken. Linking with pthread shouldn't cause a segfault.

Clang didn't segfault, which is using the same libstdc++, so that suggests it may be the compiler. I tested with gcc version 5.1.0 (Ubuntu 5.1.0-0ubuntu11~14.04.1) and found it worked, so it confirms the GCC/libstdc++ bug.

The original GCC 4.9 which was used was from an unofficial test compiler repository (https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test) - not the official Ubuntu repository. However the GCC 5.1 that was tested, was also from the same repository, so at least the bug was fixed there. It is not known as to whether the official Ubuntu GCC 4.8 causes this segfault or not.

Starting a std::thread with static linking causes segmentation fault

Removing -static solved the problem. I found out that it has nothing to do with boost or lambdas, but with static linking and std::thread, which don't seem to work together for any unknown reason (see also this post that might be related).

I guess the question why they don't work together is - though interesting - out of scope for now, and I am glad with the answer, so this can be marked as answered.

static link pthread on ubuntu causes uninitialised value jumps (valgrind)


If i don't link the library statically, there are no errors or warnings.

Linking libpthread or libc on Linux statically is almost always the wrong thing to do. Your executable may be broken in many subtle ways, if not now then in the future.

That said, the reason you get Valgrind errors is explained here.

segmentation fault using static libraries with std::jthread (g++-10)

The problem was reported to libstdc++ (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95989) and a patch has been generated to solve the problem.

Seg Fault when using pthread_create

Pthreads expect a callback function of the form void* func (void*), period. You cannot invent your own function format and expect it to work.

Furthermore the vr(x) etc parameters are function calls - you call the function once then use the result of that to tell pthread_create that it's a pointer to a callback function, which it isn't - it's just nonsense.

Also a function with a return type must always return something.

All of these problems could be avoided early on by configuring the compiler correctly, so that it gives errors upon encountering blatant bugs and invalid C, see What compiler options are recommended for beginners learning C? Correct use of functions is very fundamental stuff and something you need to grasp before moving on to more advanced topics like multi-threading.

Correct use, as was told in the friendly man:

void* vr (void* x) {
validateRows(x);
return NULL;
}

...

pthread_create(&tid[i], NULL, vr, x);

GCC: --whole-archive recipe for static linking to pthread stopped working in recent gcc versions

New workaround: -Wl,--whole-archive -lrt -lpthread -Wl,--no-whole-archive


As pointed out by Federico, adding -lrt prevents the crash. The whole issue is almost certainly related to librt, which is the Realtime Extensions library. Its timing functions (e.g., clock_gettime, clock_nanosleep) are used to implement threads.

Between Ubuntu 16.04 and 18.04, there were changes in glibc related to these functions as well. I could not figure out the details, but there are comments in the code:

/* clock_nanosleep moved to libc in version 2.17;
old binaries may expect the symbol version it had in librt. */

Also for a newer commit message:

commit 79a547b162657b3fa34d31917cc29f0e7af19e4c

Author: Adhemerval Zanella

Date: Tue Nov 5 19:59:36 2019 +0000

nptl: Move nanosleep implementation to libc

Checked on x86_64-linux-gnu and powerpc64le-linux-gnu. I also checked
the libpthread.so .gnu.version_d entries for every ABI affected and
all of them contains the required versions (including for architectures
which exports __nanosleep with a different version).

To sum it up, the workaround is to add -lrt. Note that in some examples (not here), the ordering is relevant. From the tests in gcc and some other discussion, I got the impression that first linking against librt causes less problems then linking after pthread. (In one example, only -lpthread -lrt -lpthread seemed to have worked, but it is not clear why.)

Pthread segmentation fault

There are a number of issues with your code,

  • Calculating the length of the array should be done as sizeof(arr)/sizeof(arr[0])
  • Striding for odd and even should increment the index by 2 instead of 1

Have a go with something like this:

void* odd_even(void* data)
{
int a=*((int*)data);
volatile bool sorted=false;
unsigned int arr_length = sizeof(arr)/sizeof(arr[0]);
pthread_mutex_lock(&mutex1);
while(!sorted) {
if (a==0) {
sorted=true;
for(unsigned int i=0; i < arr_length-2; i+=2) {
if(arr[i] > arr[i+2]){
std::swap(arr[i], arr[i+2]);
sorted=false;
}
}
}
else if (a==1) {
sorted=true;
for(unsigned int i=1; i < arr_length-2; i+=2){
if(arr[i] > arr[i+2]){
std::swap(arr[i], arr[i+2]);
sorted=false;
}
}
}
}//end while
pthread_mutex_unlock(&mutex1);
pthread_exit(NULL);
return nullptr;
}

EDIT. See live.



Related Topics



Leave a reply



Submit