This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[PATCH] Fix crashes with mt_allocator if libstdc++ is dlclosed (PR libstdc++/22309)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
- Date: Thu, 7 Jul 2005 13:53:19 -0400
- Subject: [PATCH] Fix crashes with mt_allocator if libstdc++ is dlclosed (PR libstdc++/22309)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
This is mainly proof of concept, but works on the testcase provided
in PR libstdc++/22309.
If mt allocator creates a key with __gthread_key_create, it should
ensure it also eventually destroys it with __gthread_key_delete,
otherwise if libstdc++.so is dlclosed, then as soon as some thread
exits afterwards, the program will crash (because key's delete handler
is still registered, but not present).
The init_priority attribute is there to make sure the key is not
deleted prematurely before other destructors are run.
2005-07-07 Jakub Jelinek <jakub@redhat.com>
PR libstdc++/22309
* src/mt_allocator.cc (__gnu_internal::__freelist_key): New type.
(__gnu_internal::freelist_key): Change to the above type.
(_M_initialize, _M_get_thread_id): Adjust users.
--- libstdc++-v3/src/mt_allocator.cc.jj 2005-06-07 12:31:09.000000000 +0200
+++ libstdc++-v3/src/mt_allocator.cc 2005-07-07 19:43:31.000000000 +0200
@@ -1,8 +1,8 @@
// Allocator details.
-// Copyright (C) 2004 Free Software Foundation, Inc.
+// Copyright (C) 2004, 2005 Free Software Foundation, Inc.
//
-// This file is part of the GNU ISO C++ Librarbooly. This library is free
+// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2, or (at your option)
@@ -40,7 +40,14 @@ namespace __gnu_internal
__glibcxx_mutex_define_initialized(freelist_mutex);
#ifdef __GTHREADS
- __gthread_key_t freelist_key;
+ struct __freelist_key
+ {
+ bool _M_init;
+ __gthread_key_t _M_key;
+ ~__freelist_key() { if (_M_init) __gthread_key_delete (_M_key); }
+ } freelist_key
+ /* Ensure freelist_key is destructed last. */
+ __attribute__((init_priority (101)));
#endif
}
@@ -454,8 +461,9 @@ namespace __gnu_cxx
// Initialize per thread key to hold pointer to
// _M_thread_freelist.
- __gthread_key_create(&__gnu_internal::freelist_key, __d);
-
+ __gthread_key_create(&__gnu_internal::freelist_key._M_key, __d);
+ __gnu_internal::freelist_key._M_init = true;
+
const size_t __max_threads = _M_options._M_max_threads + 1;
for (size_t __n = 0; __n < _M_bin_size; ++__n)
{
@@ -514,7 +522,7 @@ namespace __gnu_cxx
// returns it's id.
if (__gthread_active_p())
{
- void* v = __gthread_getspecific(__gnu_internal::freelist_key);
+ void* v = __gthread_getspecific(__gnu_internal::freelist_key._M_key);
_Thread_record* __freelist_pos = static_cast<_Thread_record*>(v);
if (__freelist_pos == NULL)
{
@@ -527,7 +535,7 @@ namespace __gnu_cxx
_M_thread_freelist = _M_thread_freelist->_M_next;
}
- __gthread_setspecific(__gnu_internal::freelist_key,
+ __gthread_setspecific(__gnu_internal::freelist_key._M_key,
static_cast<void*>(__freelist_pos));
}
return __freelist_pos->_M_id;
Jakub