diff options
author | Jason Evans <je@fb.com> | 2013-04-17 16:57:11 (GMT) |
---|---|---|
committer | Jason Evans <je@fb.com> | 2013-04-17 16:57:11 (GMT) |
commit | 741fbc6ba4499da39dd7d0c067c859fa52f1023f (patch) | |
tree | 9a307fc6ee5b2220b24b17e5757de9016f8a6365 /src | |
parent | 705328ca46ac2ae2c1d2e172917a9278107d1288 (diff) | |
download | jemalloc-741fbc6ba4499da39dd7d0c067c859fa52f1023f.zip jemalloc-741fbc6ba4499da39dd7d0c067c859fa52f1023f.tar.gz jemalloc-741fbc6ba4499da39dd7d0c067c859fa52f1023f.tar.bz2 |
Fix deadlock related to chunk_record().
Fix chunk_record() to unlock chunks_mtx before deallocating a base node,
in order to avoid potential deadlock.
Reported by Tudor Bosman.
Diffstat (limited to 'src')
-rw-r--r-- | src/chunk.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/src/chunk.c b/src/chunk.c index 044f76b..e8fc473 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -242,8 +242,6 @@ chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, node->size += size; node->zeroed = (node->zeroed && (unzeroed == false)); extent_tree_szad_insert(chunks_szad, node); - if (xnode != NULL) - base_node_dealloc(xnode); } else { /* Coalescing forward failed, so insert a new node. */ if (xnode == NULL) { @@ -253,10 +251,10 @@ chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, * already been purged, so this is only a virtual * memory leak. */ - malloc_mutex_unlock(&chunks_mtx); - return; + goto label_return; } node = xnode; + xnode = NULL; /* Prevent deallocation below. */ node->addr = chunk; node->size = size; node->zeroed = (unzeroed == false); @@ -284,7 +282,16 @@ chunk_record(extent_tree_t *chunks_szad, extent_tree_t *chunks_ad, void *chunk, base_node_dealloc(prev); } + +label_return: malloc_mutex_unlock(&chunks_mtx); + if (xnode != NULL) { + /* + * Deallocate xnode after unlocking chunks_mtx in order to + * avoid potential deadlock. + */ + base_node_dealloc(xnode); + } } void |