Fix deadlock in the arenas.purge mallctl.

Fix deadlock in the arenas.purge mallctl due to recursive mutex
acquisition.
This commit is contained in:
Jason Evans 2012-11-03 21:18:28 -07:00
parent 12efefb195
commit 34457f5144

View File

@ -113,7 +113,7 @@ CTL_PROTO(opt_prof_final)
CTL_PROTO(opt_prof_leak) CTL_PROTO(opt_prof_leak)
CTL_PROTO(opt_prof_accum) CTL_PROTO(opt_prof_accum)
CTL_PROTO(arena_i_purge) CTL_PROTO(arena_i_purge)
static int arena_purge(unsigned arena_ind); static void arena_purge(unsigned arena_ind);
CTL_PROTO(arena_i_dss) CTL_PROTO(arena_i_dss)
INDEX_PROTO(arena_i) INDEX_PROTO(arena_i)
CTL_PROTO(arenas_bin_i_size) CTL_PROTO(arenas_bin_i_size)
@ -1274,35 +1274,27 @@ CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
/******************************************************************************/ /******************************************************************************/
static int /* ctl_mutex must be held during execution of this function. */
static void
arena_purge(unsigned arena_ind) arena_purge(unsigned arena_ind)
{ {
int ret; VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);
malloc_mutex_lock(&ctl_mtx); malloc_mutex_lock(&arenas_lock);
{ memcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas);
VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas); malloc_mutex_unlock(&arenas_lock);
malloc_mutex_lock(&arenas_lock); if (arena_ind == ctl_stats.narenas) {
memcpy(tarenas, arenas, sizeof(arena_t *) * ctl_stats.narenas); unsigned i;
malloc_mutex_unlock(&arenas_lock); for (i = 0; i < ctl_stats.narenas; i++) {
if (tarenas[i] != NULL)
if (arena_ind == ctl_stats.narenas) { arena_purge_all(tarenas[i]);
unsigned i;
for (i = 0; i < ctl_stats.narenas; i++) {
if (tarenas[i] != NULL)
arena_purge_all(tarenas[i]);
}
} else {
assert(arena_ind < ctl_stats.narenas);
if (tarenas[arena_ind] != NULL)
arena_purge_all(tarenas[arena_ind]);
} }
} else {
assert(arena_ind < ctl_stats.narenas);
if (tarenas[arena_ind] != NULL)
arena_purge_all(tarenas[arena_ind]);
} }
ret = 0;
malloc_mutex_unlock(&ctl_mtx);
return (ret);
} }
static int static int
@ -1313,8 +1305,11 @@ arena_i_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
READONLY(); READONLY();
WRITEONLY(); WRITEONLY();
ret = arena_purge(mib[1]); malloc_mutex_lock(&ctl_mtx);
arena_purge(mib[1]);
malloc_mutex_unlock(&ctl_mtx);
ret = 0;
label_return: label_return:
return (ret); return (ret);
} }
@ -1483,7 +1478,8 @@ arenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
else { else {
if (arena_ind == UINT_MAX) if (arena_ind == UINT_MAX)
arena_ind = ctl_stats.narenas; arena_ind = ctl_stats.narenas;
ret = arena_purge(arena_ind); arena_purge(arena_ind);
ret = 0;
} }
label_return: label_return: