This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix crashes with mt_allocator if libstdc++ is dlclosed (PR libstdc++/22309)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]