c3f1918
commit 8a727af925be63aa6ea0f5f90e16751fd541626b
c3f1918
Author: Florian Weimer <fweimer@redhat.com>
c3f1918
Date:   Thu Apr 14 09:18:30 2016 +0200
c3f1918
c3f1918
    malloc: Remove malloc hooks from fork handler
c3f1918
    
c3f1918
    The fork handler now runs so late that there is no risk anymore that
c3f1918
    other fork handlers in the same thread use malloc, so it is no
c3f1918
    longer necessary to install malloc hooks which made a subset
c3f1918
    of malloc functionality available to the thread that called fork.
c3f1918
c3f1918
Index: b/malloc/arena.c
c3f1918
===================================================================
c3f1918
--- a/malloc/arena.c
c3f1918
+++ b/malloc/arena.c
c3f1918
@@ -137,79 +137,6 @@ int __malloc_initialized = -1;
c3f1918
 
c3f1918
 /* atfork support.  */
c3f1918
 
c3f1918
-static void *(*save_malloc_hook)(size_t __size, const void *);
c3f1918
-static void (*save_free_hook) (void *__ptr, const void *);
c3f1918
-static void *save_arena;
c3f1918
-
c3f1918
-/* Magic value for the thread-specific arena pointer when
c3f1918
-   malloc_atfork() is in use.  */
c3f1918
-
c3f1918
-# define ATFORK_ARENA_PTR ((void *) -1)
c3f1918
-
c3f1918
-/* The following hooks are used while the `atfork' handling mechanism
c3f1918
-   is active. */
c3f1918
-
c3f1918
-static void *
c3f1918
-malloc_atfork (size_t sz, const void *caller)
c3f1918
-{
c3f1918
-  void *vptr = NULL;
c3f1918
-  void *victim;
c3f1918
-
c3f1918
-  tsd_getspecific (arena_key, vptr);
c3f1918
-  if (vptr == ATFORK_ARENA_PTR)
c3f1918
-    {
c3f1918
-      /* We are the only thread that may allocate at all.  */
c3f1918
-      if (save_malloc_hook != malloc_check)
c3f1918
-        {
c3f1918
-          return _int_malloc (&main_arena, sz);
c3f1918
-        }
c3f1918
-      else
c3f1918
-        {
c3f1918
-          if (top_check () < 0)
c3f1918
-            return 0;
c3f1918
-
c3f1918
-          victim = _int_malloc (&main_arena, sz + 1);
c3f1918
-          return mem2mem_check (victim, sz);
c3f1918
-        }
c3f1918
-    }
c3f1918
-  else
c3f1918
-    {
c3f1918
-      /* Suspend the thread until the `atfork' handlers have completed.
c3f1918
-         By that time, the hooks will have been reset as well, so that
c3f1918
-         mALLOc() can be used again. */
c3f1918
-      (void) mutex_lock (&list_lock);
c3f1918
-      (void) mutex_unlock (&list_lock);
c3f1918
-      return __libc_malloc (sz);
c3f1918
-    }
c3f1918
-}
c3f1918
-
c3f1918
-static void
c3f1918
-free_atfork (void *mem, const void *caller)
c3f1918
-{
c3f1918
-  void *vptr = NULL;
c3f1918
-  mstate ar_ptr;
c3f1918
-  mchunkptr p;                          /* chunk corresponding to mem */
c3f1918
-
c3f1918
-  if (mem == 0)                              /* free(0) has no effect */
c3f1918
-    return;
c3f1918
-
c3f1918
-  p = mem2chunk (mem);         /* do not bother to replicate free_check here */
c3f1918
-
c3f1918
-  if (chunk_is_mmapped (p))                       /* release mmapped memory. */
c3f1918
-    {
c3f1918
-      munmap_chunk (p);
c3f1918
-      return;
c3f1918
-    }
c3f1918
-
c3f1918
-  ar_ptr = arena_for_chunk (p);
c3f1918
-  tsd_getspecific (arena_key, vptr);
c3f1918
-  _int_free (ar_ptr, p, vptr == ATFORK_ARENA_PTR);
c3f1918
-}
c3f1918
-
c3f1918
-
c3f1918
-/* Counter for number of times the list is locked by the same thread.  */
c3f1918
-static unsigned int atfork_recursive_cntr;
c3f1918
-
c3f1918
 /* The following three functions are called around fork from a
c3f1918
    multi-threaded process.  We do not use the general fork handler
c3f1918
    mechanism to make sure that our handlers are the last ones being
c3f1918
@@ -219,65 +146,29 @@ static unsigned int atfork_recursive_cnt
c3f1918
 void
c3f1918
 __malloc_fork_lock_parent (void)
c3f1918
 {
c3f1918
-  mstate ar_ptr;
c3f1918
-
c3f1918
   if (__malloc_initialized < 1)
c3f1918
     return;
c3f1918
 
c3f1918
   /* We do not acquire free_list_lock here because we completely
c3f1918
      reconstruct free_list in __malloc_fork_unlock_child.  */
c3f1918
 
c3f1918
-  if (mutex_trylock (&list_lock))
c3f1918
-    {
c3f1918
-      void *my_arena;
c3f1918
-      tsd_getspecific (arena_key, my_arena);
c3f1918
-      if (my_arena == ATFORK_ARENA_PTR)
c3f1918
-        /* This is the same thread which already locks the global list.
c3f1918
-           Just bump the counter.  */
c3f1918
-        goto out;
c3f1918
-
c3f1918
-      /* This thread has to wait its turn.  */
c3f1918
-      (void) mutex_lock (&list_lock);
c3f1918
-    }
c3f1918
-  for (ar_ptr = &main_arena;; )
c3f1918
+  (void) mutex_lock (&list_lock);
c3f1918
+  for (mstate ar_ptr = &main_arena;; )
c3f1918
     {
c3f1918
       (void) mutex_lock (&ar_ptr->mutex);
c3f1918
       ar_ptr = ar_ptr->next;
c3f1918
       if (ar_ptr == &main_arena)
c3f1918
         break;
c3f1918
     }
c3f1918
-  save_malloc_hook = __malloc_hook;
c3f1918
-  save_free_hook = __free_hook;
c3f1918
-  __malloc_hook = malloc_atfork;
c3f1918
-  __free_hook = free_atfork;
c3f1918
-  /* Only the current thread may perform malloc/free calls now.
c3f1918
-     save_arena will be reattached to the current thread, in
c3f1918
-     __malloc_fork_lock_parent, so save_arena->attached_threads is not
c3f1918
-     updated.  */
c3f1918
-  tsd_getspecific (arena_key, save_arena);
c3f1918
-  tsd_setspecific (arena_key, ATFORK_ARENA_PTR);
c3f1918
-out:
c3f1918
-  ++atfork_recursive_cntr;
c3f1918
 }
c3f1918
 
c3f1918
 void
c3f1918
 __malloc_fork_unlock_parent (void)
c3f1918
 {
c3f1918
-  mstate ar_ptr;
c3f1918
-
c3f1918
   if (__malloc_initialized < 1)
c3f1918
     return;
c3f1918
 
c3f1918
-  if (--atfork_recursive_cntr != 0)
c3f1918
-    return;
c3f1918
-
c3f1918
-  /* Replace ATFORK_ARENA_PTR with save_arena.
c3f1918
-     save_arena->attached_threads was not changed in
c3f1918
-     __malloc_fork_lock_parent and is still correct.  */
c3f1918
-  tsd_setspecific (arena_key, save_arena);
c3f1918
-  __malloc_hook = save_malloc_hook;
c3f1918
-  __free_hook = save_free_hook;
c3f1918
-  for (ar_ptr = &main_arena;; )
c3f1918
+  for (mstate ar_ptr = &main_arena;; )
c3f1918
     {
c3f1918
       (void) mutex_unlock (&ar_ptr->mutex);
c3f1918
       ar_ptr = ar_ptr->next;
c3f1918
@@ -290,25 +181,22 @@ __malloc_fork_unlock_parent (void)
c3f1918
 void
c3f1918
 __malloc_fork_unlock_child (void)
c3f1918
 {
c3f1918
-  mstate ar_ptr;
c3f1918
-
c3f1918
   if (__malloc_initialized < 1)
c3f1918
     return;
c3f1918
 
c3f1918
-  tsd_setspecific (arena_key, save_arena);
c3f1918
-  __malloc_hook = save_malloc_hook;
c3f1918
-  __free_hook = save_free_hook;
c3f1918
+  void *vptr = NULL;
c3f1918
+  mstate current_arena = tsd_getspecific (arena_key, vptr);
c3f1918
 
c3f1918
-  /* Push all arenas to the free list, except save_arena, which is
c3f1918
+  /* Push all arenas to the free list, except current_arena, which is
c3f1918
      attached to the current thread.  */
c3f1918
   mutex_init (&free_list_lock);
c3f1918
-  if (save_arena != NULL)
c3f1918
-    ((mstate) save_arena)->attached_threads = 1;
c3f1918
+  if (current_arena != NULL)
c3f1918
+    current_arena->attached_threads = 1;
c3f1918
   free_list = NULL;
c3f1918
-  for (ar_ptr = &main_arena;; )
c3f1918
+  for (mstate ar_ptr = &main_arena;; )
c3f1918
     {
c3f1918
       mutex_init (&ar_ptr->mutex);
c3f1918
-      if (ar_ptr != save_arena)
c3f1918
+      if (ar_ptr != current_arena)
c3f1918
         {
c3f1918
 	  /* This arena is no longer attached to any thread.  */
c3f1918
 	  ar_ptr->attached_threads = 0;
c3f1918
@@ -321,7 +209,6 @@ __malloc_fork_unlock_child (void)
c3f1918
     }
c3f1918
 
c3f1918
   mutex_init (&list_lock);
c3f1918
-  atfork_recursive_cntr = 0;
c3f1918
 }
c3f1918
 
c3f1918
 /* Initialization routine. */
c3f1918
Index: b/malloc/malloc.c
c3f1918
===================================================================
c3f1918
--- a/malloc/malloc.c
c3f1918
+++ b/malloc/malloc.c
c3f1918
@@ -1075,8 +1075,6 @@ static void*   realloc_check(void* oldme
c3f1918
 			       const void *caller);
c3f1918
 static void*   memalign_check(size_t alignment, size_t bytes,
c3f1918
 				const void *caller);
c3f1918
-static void*   malloc_atfork(size_t sz, const void *caller);
c3f1918
-static void      free_atfork(void* mem, const void *caller);
c3f1918
 
c3f1918
 /* ------------------ MMAP support ------------------  */
c3f1918