Bug 1332508 - Reinitialize allocator mutexes in fork() child processes. r?njn
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.
--- 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