Search code examples
c++segmentation-faultpthreadsmingw32thread-local-storage

Why do I get a segmentation fault when adding ltalloc with MinGW


I tried to build my application with ltalloc. I tried it with MinGW32 4.9.1 and MinGW64-32 4.9.2. It compiles and links fine but when I run it a Segmentation Fault occurs. Debugging pinpointed the problem to the following code:

#include <pthread.h>
#pragma weak pthread_once
#pragma weak pthread_key_create
#pragma weak pthread_setspecific
static pthread_key_t pthread_key;
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
static void init_pthread_key() { pthread_key_create(&pthread_key, release_thread_cache); }
static thread_local int thread_initialized = 0;
static void init_pthread_destructor()//must be called only when some block placed into a thread cache's free list
{
    if (unlikely(!thread_initialized))
    {
        thread_initialized = 1;
        if (pthread_once)
        {
            pthread_once(&init_once, init_pthread_key);  // <--- THIS CAUSES THE SEGSEGV
            pthread_setspecific(pthread_key, (void*)1);//set nonzero value to force calling of release_thread_cache() on thread terminate
        }
    }
}

As far as I know both versions support thread-local storage natively. The Wiki of of ltalloc also wrote the following:

Warning: in some builds of MinGW there is a problem with emutls and order of execution of thread destructor (all thread local variables destructed before it), and termination of any thread will lead to application crash.

Unfortunately this warning doesn't tell me anything. Googling it also didn't make me smarter.


Solution

  • Out of the blue, try this:

    static void init_pthread_key(void) 
    { 
      if (pthread_key_create)
      {
        pthread_key_create(&pthread_key, release_thread_cache); 
      }
    }
    

    Also adding full error checking to the pthread_* might not only help during debugging.