summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Evans <je@fb.com>2013-04-17 16:57:11 (GMT)
committerJason Evans <je@fb.com>2013-04-17 16:57:11 (GMT)
commit741fbc6ba4499da39dd7d0c067c859fa52f1023f (patch)
tree9a307fc6ee5b2220b24b17e5757de9016f8a6365 /src
parent705328ca46ac2ae2c1d2e172917a9278107d1288 (diff)
downloadjemalloc-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.c15
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