aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJason Evans <je@fb.com>2016-03-30 18:36:04 -0700
committerChristopher Ferris <cferris@google.com>2016-05-05 15:52:07 -0700
commitc7682d72e8eeca87831dd36e09888ecd22a25f17 (patch)
tree41cbb603d1e1602b2334b1d050052b12e61c85c0 /src
parentb32837faaa5b0b0f25652c389c4503304fe9fac8 (diff)
downloadjemalloc-c7682d72e8eeca87831dd36e09888ecd22a25f17.tar.gz
Move chunk_dalloc_arena()'s implementation into chunk_dalloc_wrapper(), so that if the dalloc hook fails, proper decommit/purge/retain cascading occurs. This fixes three potential chunk leaks on OOM paths, one during dss-based chunk allocation, one during chunk header commit (currently relevant only on Windows), and one during rtree write (e.g. if rtree node allocation fails). Merge chunk_purge_arena() into chunk_purge_default() (refactor, no change to functionality). Bug: 28590121 (cherry picked from commit 1ae9287a1aec534fa0a805a717f1c4e058ae8433) Change-Id: Ia21292ab25c65bb7a8aa44077c86545789a9e786
Diffstat (limited to 'src')
-rw-r--r--src/arena.c16
-rw-r--r--src/chunk.c51
-rw-r--r--src/chunk_dss.c2
3 files changed, 25 insertions, 44 deletions
diff --git a/src/arena.c b/src/arena.c
index 965c0fe..b7645d8 100644
--- a/src/arena.c
+++ b/src/arena.c
@@ -617,8 +617,8 @@ arena_chunk_alloc_internal_hard(arena_t *arena, chunk_hooks_t *chunk_hooks,
/* Commit header. */
if (chunk_hooks->commit(chunk, chunksize, 0, map_bias <<
LG_PAGE, arena->ind)) {
- chunk_dalloc_wrapper(arena, chunk_hooks,
- (void *)chunk, chunksize, *commit);
+ chunk_dalloc_wrapper(arena, chunk_hooks, (void *)chunk,
+ chunksize, *zero, *commit);
chunk = NULL;
}
}
@@ -629,7 +629,7 @@ arena_chunk_alloc_internal_hard(arena_t *arena, chunk_hooks_t *chunk_hooks,
LG_PAGE, arena->ind);
}
chunk_dalloc_wrapper(arena, chunk_hooks, (void *)chunk,
- chunksize, *commit);
+ chunksize, *zero, *commit);
chunk = NULL;
}
@@ -1024,7 +1024,7 @@ arena_chunk_ralloc_huge_expand_hard(arena_t *arena, chunk_hooks_t *chunk_hooks,
malloc_mutex_unlock(&arena->lock);
} else if (chunk_hooks->merge(chunk, CHUNK_CEILING(oldsize), nchunk,
cdiff, true, arena->ind)) {
- chunk_dalloc_arena(arena, chunk_hooks, nchunk, cdiff, *zero,
+ chunk_dalloc_wrapper(arena, chunk_hooks, nchunk, cdiff, *zero,
true);
err = true;
}
@@ -1050,8 +1050,8 @@ arena_chunk_ralloc_huge_expand(arena_t *arena, void *chunk, size_t oldsize,
}
arena_nactive_add(arena, udiff >> LG_PAGE);
- err = (chunk_alloc_cache(arena, &arena->chunk_hooks, nchunk, cdiff,
- chunksize, zero, true) == NULL);
+ err = (chunk_alloc_cache(arena, &chunk_hooks, nchunk, cdiff, chunksize,
+ zero, true) == NULL);
malloc_mutex_unlock(&arena->lock);
if (err) {
err = arena_chunk_ralloc_huge_expand_hard(arena, &chunk_hooks,
@@ -1059,7 +1059,7 @@ arena_chunk_ralloc_huge_expand(arena_t *arena, void *chunk, size_t oldsize,
cdiff);
} else if (chunk_hooks.merge(chunk, CHUNK_CEILING(oldsize), nchunk,
cdiff, true, arena->ind)) {
- chunk_dalloc_arena(arena, &chunk_hooks, nchunk, cdiff, *zero,
+ chunk_dalloc_wrapper(arena, &chunk_hooks, nchunk, cdiff, *zero,
true);
err = true;
}
@@ -1707,7 +1707,7 @@ arena_unstash_purged(arena_t *arena, chunk_hooks_t *chunk_hooks,
extent_node_dirty_remove(chunkselm);
arena_node_dalloc(arena, chunkselm);
chunkselm = chunkselm_next;
- chunk_dalloc_arena(arena, chunk_hooks, addr, size,
+ chunk_dalloc_wrapper(arena, chunk_hooks, addr, size,
zeroed, committed);
} else {
arena_chunk_t *chunk =
diff --git a/src/chunk.c b/src/chunk.c
index b179d21..304d4e5 100644
--- a/src/chunk.c
+++ b/src/chunk.c
@@ -425,8 +425,8 @@ chunk_alloc_default(void *new_addr, size_t size, size_t alignment, bool *zero,
arena_t *arena;
arena = chunk_arena_get(arena_ind);
- ret = chunk_alloc_core(arena, new_addr, size, alignment, zero,
- commit, arena->dss_prec);
+ ret = chunk_alloc_core(arena, new_addr, size, alignment, zero, commit,
+ arena->dss_prec);
if (ret == NULL)
return (NULL);
if (config_valgrind)
@@ -579,8 +579,18 @@ chunk_dalloc_cache(arena_t *arena, chunk_hooks_t *chunk_hooks, void *chunk,
arena_maybe_purge(arena);
}
+static bool
+chunk_dalloc_default(void *chunk, size_t size, bool committed,
+ unsigned arena_ind)
+{
+
+ if (!have_dss || !chunk_in_dss(chunk))
+ return (chunk_dalloc_mmap(chunk, size));
+ return (true);
+}
+
void
-chunk_dalloc_arena(arena_t *arena, chunk_hooks_t *chunk_hooks, void *chunk,
+chunk_dalloc_wrapper(arena_t *arena, chunk_hooks_t *chunk_hooks, void *chunk,
size_t size, bool zeroed, bool committed)
{
@@ -605,27 +615,6 @@ chunk_dalloc_arena(arena_t *arena, chunk_hooks_t *chunk_hooks, void *chunk,
}
static bool
-chunk_dalloc_default(void *chunk, size_t size, bool committed,
- unsigned arena_ind)
-{
-
- if (!have_dss || !chunk_in_dss(chunk))
- return (chunk_dalloc_mmap(chunk, size));
- return (true);
-}
-
-void
-chunk_dalloc_wrapper(arena_t *arena, chunk_hooks_t *chunk_hooks, void *chunk,
- size_t size, bool committed)
-{
-
- chunk_hooks_assure_initialized(arena, chunk_hooks);
- chunk_hooks->dalloc(chunk, size, committed, arena->ind);
- if (config_valgrind && chunk_hooks->dalloc != chunk_dalloc_default)
- JEMALLOC_VALGRIND_MAKE_MEM_NOACCESS(chunk, size);
-}
-
-static bool
chunk_commit_default(void *chunk, size_t size, size_t offset, size_t length,
unsigned arena_ind)
{
@@ -643,8 +632,9 @@ chunk_decommit_default(void *chunk, size_t size, size_t offset, size_t length,
length));
}
-bool
-chunk_purge_arena(arena_t *arena, void *chunk, size_t offset, size_t length)
+static bool
+chunk_purge_default(void *chunk, size_t size, size_t offset, size_t length,
+ unsigned arena_ind)
{
assert(chunk != NULL);
@@ -657,15 +647,6 @@ chunk_purge_arena(arena_t *arena, void *chunk, size_t offset, size_t length)
length));
}
-static bool
-chunk_purge_default(void *chunk, size_t size, size_t offset, size_t length,
- unsigned arena_ind)
-{
-
- return (chunk_purge_arena(chunk_arena_get(arena_ind), chunk, offset,
- length));
-}
-
bool
chunk_purge_wrapper(arena_t *arena, chunk_hooks_t *chunk_hooks, void *chunk,
size_t size, size_t offset, size_t length)
diff --git a/src/chunk_dss.c b/src/chunk_dss.c
index 61fc916..943d0e9 100644
--- a/src/chunk_dss.c
+++ b/src/chunk_dss.c
@@ -136,7 +136,7 @@ chunk_alloc_dss(arena_t *arena, void *new_addr, size_t size, size_t alignment,
CHUNK_HOOKS_INITIALIZER;
chunk_dalloc_wrapper(arena,
&chunk_hooks, cpad, cpad_size,
- true);
+ false, true);
}
if (*zero) {
JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(