Bug 1332508 - Reinitialize allocator mutexes in fork() child processes. r=njn a=jorgk DONTBUILD THUNDERBIRD520b4_2017022301_RELBRANCH
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 20 Jan 2017 10:06:41 +0900
branchTHUNDERBIRD520b4_2017022301_RELBRANCH
changeset 367261 7659278b0a9bb59075aeb1f6d78b16b1abb4eba8
parent 367260 3d63c41abefea382a55eab2d438d021bb10fd597
child 367291 48ab0579ee3a2da0646c4ca60a9bb7f31ccce53d
push id6963
push usermozilla@jorgk.com
push dateThu, 23 Feb 2017 13:32:44 +0000
treeherdermozilla-beta@7659278b0a9b [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 DONTBUILD 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