about summary refs log tree commit diff
path: root/malloc/arena.c
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2015-12-16 12:39:48 +0100
committerFlorian Weimer <fweimer@redhat.com>2015-12-16 12:39:48 +0100
commit3da825ce483903e3a881a016113b3e59fd4041de (patch)
tree092a1973785289ec3bd6bb2eb9c40064608d33b6 /malloc/arena.c
parentf1aceee39289f97a420126c58007eba77fb2dd30 (diff)
downloadglibc-3da825ce483903e3a881a016113b3e59fd4041de.tar.gz
glibc-3da825ce483903e3a881a016113b3e59fd4041de.tar.xz
glibc-3da825ce483903e3a881a016113b3e59fd4041de.zip
malloc: Fix attached thread reference count handling [BZ #19243]
reused_arena can increase the attached thread count of arenas on the
free list.  This means that the assertion that the reference count is
zero is incorrect.  In this case, the reference count initialization
is incorrect as well and could cause arenas to be put on the free
list too early (while they still have attached threads).

	* malloc/arena.c (get_free_list): Remove assert and adjust
	reference count handling.  Add comment about reused_arena
	interaction.
	(reused_arena): Add comments abount get_free_list interaction.
	* malloc/tst-malloc-thread-exit.c: New file.
	* malloc/Makefile (tests): Add tst-malloc-thread-exit.
	(tst-malloc-thread-exit): Link against libpthread.
Diffstat (limited to 'malloc/arena.c')
-rw-r--r--malloc/arena.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/malloc/arena.c b/malloc/arena.c
index 3dab7bb297..73bda84b57 100644
--- a/malloc/arena.c
+++ b/malloc/arena.c
@@ -805,6 +805,8 @@ _int_new_arena (size_t size)
 }
 
 
+/* Remove an arena from free_list.  The arena may be in use because it
+   was attached concurrently to a thread by reused_arena below.  */
 static mstate
 get_free_list (void)
 {
@@ -818,10 +820,8 @@ get_free_list (void)
 	{
 	  free_list = result->next_free;
 
-	  /* Arenas on the free list are not attached to any thread.  */
-	  assert (result->attached_threads == 0);
-	  /* But the arena will now be attached to this thread.  */
-	  result->attached_threads = 1;
+	  /* The arena will be attached to this thread.  */
+	  ++result->attached_threads;
 
 	  detach_arena (replaced_arena);
 	}
@@ -849,6 +849,8 @@ reused_arena (mstate avoid_arena)
   if (next_to_use == NULL)
     next_to_use = &main_arena;
 
+  /* Iterate over all arenas (including those linked from
+     free_list).  */
   result = next_to_use;
   do
     {
@@ -883,6 +885,8 @@ reused_arena (mstate avoid_arena)
   (void) mutex_lock (&result->mutex);
 
 out:
+  /* Attach the arena to the current thread.  Note that we may have
+     selected an arena which was on free_list.  */
   {
     mstate replaced_arena = thread_arena;
     (void) mutex_lock (&list_lock);