All,

The enclosed testcases (very close to ext/mt_allocator/deallocate_global_thread-1.cc) exposes a pattern where the following sequence is called (when __gthread_active_p is enabled) :

    __gthread_key_create(&key,::_M_destroy_thread_key);
    __gthread_setspecific(key, (void*)_M_id);
    __gthread_key_delete(key);
    __gthread_setspecific(key, (void*)_M_id);


Even, if this works perfectly using pthreads, it seems to me that this is an illegal use of threads. When using another thread implementation, (i.e. when the key is implemented as a pointer). In my case: - the key_create allocates the memory, and returns the pointer to the allocated memory
 - the key_delete frees this memory,
 - the setspecific uses this freed memory.

If I m right saying this is an illegal use of threads, a possible quick patch for mt_allocator.cc could be the one enclosed.

Let me know what you think of this approach.

Thanks.
Laurent


// 20.4.1.1 allocator members

#include <list>
#include <string>
#include <stdexcept>
#include <cstdio>
#include <ext/mt_allocator.h>

#include <pthread.h>

typedef std::string value_type;
using __gnu_cxx::__pool;
using __gnu_cxx::__common_pool_policy;
typedef __common_pool_policy<__pool, true> policy_type;
typedef __gnu_cxx::__mt_alloc<value_type, policy_type> allocator_type;
typedef std::char_traits<value_type> traits_type;
typedef std::list<value_type, allocator_type> list_type;

list_type l;


void *my_thread_process (void * arg)
{
  printf ("Thread %s\n", (char*)arg);
  pthread_exit (0);
}


int main()
{
  pthread_t th1;
  if (pthread_create (&th1, NULL, my_thread_process, (void*)"1") < 0) {
    fprintf (stderr, "pthread_create error for thread 1\n");
    exit (1);
  }

  l.push_back("bayou bend");

  return 0;
}
2012-04-19  Laurent Alfonsi  <laurent.alfo...@st.com>

    * src/c++98/mt_allocator.cc: Define/use an illegal thread key
    (struct __freelist, __freelist::~__freelist()): set to illegal key
    (pool<true>::_M_get_thread_id()): Check _M_key before using it


Index: src/c++98/mt_allocator.cc
===================================================================
--- src/c++98/mt_allocator.cc.orig
+++ src/c++98/mt_allocator.cc
@@ -34,19 +34,22 @@
 namespace
 {
 #ifdef __GTHREADS
+  const __gthread_key_t ILLEGAL_THREAD_KEY = -1;
+
   struct __freelist
   {
     typedef __gnu_cxx::__pool<true>::_Thread_record _Thread_record;
     _Thread_record*    _M_thread_freelist;
     _Thread_record*    _M_thread_freelist_array;
     size_t             _M_max_threads;
-    __gthread_key_t    _M_key;
+    __gthread_key_t    _M_key = ILLEGAL_THREAD_KEY;
 
     ~__freelist()
     {
       if (_M_thread_freelist_array)
        {
          __gthread_key_delete(_M_key);
+         _M_key = ILLEGAL_THREAD_KEY;
          ::operator delete(static_cast<void*>(_M_thread_freelist_array));
          _M_thread_freelist = 0;
        }
@@ -640,7 +643,8 @@
                }
            }
 
-            __gthread_setspecific(freelist._M_key, (void*)_M_id);
+           if (freelist._M_key!=ILLEGAL_THREAD_KEY)
+             __gthread_setspecific(freelist._M_key, (void*)_M_id);
          }
        return _M_id >= _M_options._M_max_threads ? 0 : _M_id;
       }

Reply via email to