Bug 1332508 - Reinitialize allocator mutexes in fork() child processes. r=njn a=jorgk THUNDERBIRD520b2_2017020901_RELBRANCH
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 20 Jan 2017 10:06:41 +0900
branchTHUNDERBIRD520b2_2017020901_RELBRANCH
changeset 367006 5f22c17aeac24ce0854f80521e13fb17f601c744
parent 367005 861ac63842ddecc44ad242e16472a90341c05a38
child 367012 92a658ace96c4d38052a3c3099e87c4c264052cf
child 575581 4c28f104c76603cf7c2e5719dafcc7fbd2d5d306
push id6903
push usermozilla@jorgk.com
push dateThu, 09 Feb 2017 17:57:13 +0000
treeherdermozilla-beta@5f22c17aeac2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn, jorgk
bugs1332508
milestone52.0
Bug 1332508 - Reinitialize allocator mutexes in fork() child processes. r=njn a=jorgk Adapted from https://github.com/jemalloc/jemalloc/commit/4e2e3dd9cf19ed5991938a708a8b50611aa5bbf8 and https://github.com/jemalloc/jemalloc/commit/d9f7b2a4307f7ff9f7a139b33d366d44e8a8b83d As per the latter commit, it would seem unlocking, in fork() child processes, mutexes that were locked in the parent process is not really well supported on OSX 10.12. The addition of the zone_reinit_lock function in 10.12 supports this idea.
memory/build/zone.c
memory/mozjemalloc/jemalloc.c
--- a/memory/build/zone.c
+++ b/memory/build/zone.c
@@ -248,40 +248,40 @@ zone_force_lock(malloc_zone_t *zone)
   if (isthreaded)
     jemalloc_prefork();
 }
 
 static void
 zone_force_unlock(malloc_zone_t *zone)
 {
   /* /!\ This calls into jemalloc. It works because we're linked in the
-   * same library. Stolen from jemalloc's zone.c. */
+   * same library. Stolen from jemalloc's zone.c. See the comment there. */
   if (isthreaded)
-    jemalloc_postfork_parent();
+    jemalloc_postfork_child();
 }
 
 #else
 
 extern void _malloc_prefork(void);
-extern void _malloc_postfork(void);
+extern void _malloc_postfork_child(void);
 
 static void
 zone_force_lock(malloc_zone_t *zone)
 {
   /* /!\ This calls into mozjemalloc. It works because we're linked in the
    * same library. */
   _malloc_prefork();
 }
 
 static void
 zone_force_unlock(malloc_zone_t *zone)
 {
   /* /!\ This calls into mozjemalloc. It works because we're linked in the
    * same library. */
-  _malloc_postfork();
+  _malloc_postfork_child();
 }
 
 #endif
 
 static void
 zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats)
 {
   /* We make no effort to actually fill the values */
--- a/memory/mozjemalloc/jemalloc.c
+++ b/memory/mozjemalloc/jemalloc.c
@@ -1453,17 +1453,21 @@ bool		malloc_init_hard(void);
 
 #ifndef MOZ_MEMORY_DARWIN
 static
 #endif
 void	_malloc_prefork(void);
 #ifndef MOZ_MEMORY_DARWIN
 static
 #endif
-void	_malloc_postfork(void);
+void	_malloc_postfork_parent(void);
+#ifndef MOZ_MEMORY_DARWIN
+static
+#endif
+void	_malloc_postfork_child(void);
 
 /*
  * End function prototypes.
  */
 /******************************************************************************/
 
 static inline size_t
 load_acquire_z(size_t *p)
@@ -6034,17 +6038,17 @@ MALLOC_OUT:
 	if (chunk_rtree == NULL)
 		return (true);
 #endif
 
 	malloc_initialized = true;
 
 #if !defined(MOZ_MEMORY_WINDOWS) && !defined(MOZ_MEMORY_DARWIN)
 	/* Prevent potential deadlock on malloc locks after fork. */
-	pthread_atfork(_malloc_prefork, _malloc_postfork, _malloc_postfork);
+	pthread_atfork(_malloc_prefork, _malloc_postfork_parent, _malloc_postfork_child);
 #endif
 
 #if defined(NEEDS_PTHREAD_MMAP_UNALIGNED_TSD)
 	if (pthread_key_create(&mmap_unaligned_tsd, NULL) != 0) {
 		malloc_printf("<jemalloc>: Error in pthread_key_create()\n");
 	}
 #endif
 
@@ -6779,33 +6783,54 @@ void
 
 	malloc_mutex_lock(&huge_mtx);
 }
 
 #ifndef MOZ_MEMORY_DARWIN
 static
 #endif
 void
-_malloc_postfork(void)
+_malloc_postfork_parent(void)
 {
 	unsigned i;
 
 	/* Release all mutexes, now that fork() has completed. */
 
 	malloc_mutex_unlock(&huge_mtx);
 
 	malloc_mutex_unlock(&base_mtx);
 
 	for (i = 0; i < narenas; i++) {
 		if (arenas[i] != NULL)
 			malloc_spin_unlock(&arenas[i]->lock);
 	}
 	malloc_spin_unlock(&arenas_lock);
 }
 
+#ifndef MOZ_MEMORY_DARWIN
+static
+#endif
+void
+_malloc_postfork_child(void)
+{
+	unsigned i;
+
+	/* Reinitialize all mutexes, now that fork() has completed. */
+
+	malloc_mutex_init(&huge_mtx);
+
+	malloc_mutex_init(&base_mtx);
+
+	for (i = 0; i < narenas; i++) {
+		if (arenas[i] != NULL)
+			malloc_spin_init(&arenas[i]->lock);
+	}
+	malloc_spin_init(&arenas_lock);
+}
+
 /*
  * End library-private functions.
  */
 /******************************************************************************/
 
 #ifdef HAVE_DLOPEN
 #  include <dlfcn.h>
 #endif