diff options
author | Jason Evans <je@fb.com> | 2012-03-13 23:31:41 (GMT) |
---|---|---|
committer | Jason Evans <je@fb.com> | 2012-03-13 23:31:41 (GMT) |
commit | 4e2e3dd9cf19ed5991938a708a8b50611aa5bbf8 (patch) | |
tree | 0bd52cef3ce19d84725e6018a5b41bc6cdb8de2a /src/jemalloc.c | |
parent | 824d34e5b7f5cf00bf472ec79f7ec1c6e3474114 (diff) | |
download | jemalloc-4e2e3dd9cf19ed5991938a708a8b50611aa5bbf8.zip jemalloc-4e2e3dd9cf19ed5991938a708a8b50611aa5bbf8.tar.gz jemalloc-4e2e3dd9cf19ed5991938a708a8b50611aa5bbf8.tar.bz2 |
Fix fork-related bugs.
Acquire/release arena bin locks as part of the prefork/postfork. This
bug made deadlock in the child between fork and exec a possibility.
Split jemalloc_postfork() into jemalloc_postfork_{parent,child}() so
that the child can reinitialize mutexes rather than unlocking them. In
practice, this bug tended not to cause problems.
Diffstat (limited to 'src/jemalloc.c')
-rw-r--r-- | src/jemalloc.c | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/src/jemalloc.c b/src/jemalloc.c index 2f3f372..385eb03 100644 --- a/src/jemalloc.c +++ b/src/jemalloc.c @@ -610,8 +610,8 @@ malloc_init_hard(void) malloc_conf_init(); /* Register fork handlers. */ - if (pthread_atfork(jemalloc_prefork, jemalloc_postfork, - jemalloc_postfork) != 0) { + if (pthread_atfork(jemalloc_prefork, jemalloc_postfork_parent, + jemalloc_postfork_child) != 0) { malloc_write("<jemalloc>: Error in pthread_atfork()\n"); if (opt_abort) abort(); @@ -1593,40 +1593,46 @@ jemalloc_prefork(void) unsigned i; /* Acquire all mutexes in a safe order. */ - - malloc_mutex_lock(&arenas_lock); + malloc_mutex_prefork(&arenas_lock); for (i = 0; i < narenas; i++) { if (arenas[i] != NULL) - malloc_mutex_lock(&arenas[i]->lock); + arena_prefork(arenas[i]); } - - malloc_mutex_lock(&base_mtx); - - malloc_mutex_lock(&huge_mtx); - - if (config_dss) - malloc_mutex_lock(&dss_mtx); + base_prefork(); + huge_prefork(); + chunk_dss_prefork(); } void -jemalloc_postfork(void) +jemalloc_postfork_parent(void) { unsigned i; /* Release all mutexes, now that fork() has completed. */ + chunk_dss_postfork_parent(); + huge_postfork_parent(); + base_postfork_parent(); + for (i = 0; i < narenas; i++) { + if (arenas[i] != NULL) + arena_postfork_parent(arenas[i]); + } + malloc_mutex_postfork_parent(&arenas_lock); +} - if (config_dss) - malloc_mutex_unlock(&dss_mtx); - - malloc_mutex_unlock(&huge_mtx); - - malloc_mutex_unlock(&base_mtx); +void +jemalloc_postfork_child(void) +{ + unsigned i; + /* Release all mutexes, now that fork() has completed. */ + chunk_dss_postfork_child(); + huge_postfork_child(); + base_postfork_child(); for (i = 0; i < narenas; i++) { if (arenas[i] != NULL) - malloc_mutex_unlock(&arenas[i]->lock); + arena_postfork_child(arenas[i]); } - malloc_mutex_unlock(&arenas_lock); + malloc_mutex_postfork_child(&arenas_lock); } /******************************************************************************/ |