Fix a prof-related race condition.
Fix prof_lookup() to artificially raise curobjs for all paths through the code that creates a new entry in the per thread bt2cnt hash table. This fixes a race condition that could corrupt memory if prof_accum were false, and a non-default lg_prof_tcmax were used and/or threads were destroyed.
This commit is contained in:
parent
46405e670f
commit
a9076c9483
25
src/prof.c
25
src/prof.c
@ -474,11 +474,23 @@ prof_lookup(prof_bt_t *bt)
|
|||||||
/*
|
/*
|
||||||
* Artificially raise curobjs, in order to avoid a race
|
* Artificially raise curobjs, in order to avoid a race
|
||||||
* condition with prof_ctx_merge()/prof_ctx_destroy().
|
* condition with prof_ctx_merge()/prof_ctx_destroy().
|
||||||
|
*
|
||||||
|
* No locking is necessary for ctx here because no other
|
||||||
|
* threads have had the opportunity to fetch it from
|
||||||
|
* bt2ctx yet.
|
||||||
*/
|
*/
|
||||||
ctx.p->cnt_merged.curobjs++;
|
ctx.p->cnt_merged.curobjs++;
|
||||||
new_ctx = true;
|
new_ctx = true;
|
||||||
} else
|
} else {
|
||||||
|
/*
|
||||||
|
* Artificially raise curobjs, in order to avoid a race
|
||||||
|
* condition with prof_ctx_merge()/prof_ctx_destroy().
|
||||||
|
*/
|
||||||
|
malloc_mutex_lock(&ctx.p->lock);
|
||||||
|
ctx.p->cnt_merged.curobjs++;
|
||||||
|
malloc_mutex_unlock(&ctx.p->lock);
|
||||||
new_ctx = false;
|
new_ctx = false;
|
||||||
|
}
|
||||||
prof_leave();
|
prof_leave();
|
||||||
|
|
||||||
/* Link a prof_thd_cnt_t into ctx for this thread. */
|
/* Link a prof_thd_cnt_t into ctx for this thread. */
|
||||||
@ -491,8 +503,9 @@ prof_lookup(prof_bt_t *bt)
|
|||||||
*/
|
*/
|
||||||
ret.p = ql_last(&prof_tdata->lru_ql, lru_link);
|
ret.p = ql_last(&prof_tdata->lru_ql, lru_link);
|
||||||
assert(ret.v != NULL);
|
assert(ret.v != NULL);
|
||||||
ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt, NULL,
|
if (ckh_remove(&prof_tdata->bt2cnt, ret.p->ctx->bt,
|
||||||
NULL);
|
NULL, NULL))
|
||||||
|
assert(false);
|
||||||
ql_remove(&prof_tdata->lru_ql, ret.p, lru_link);
|
ql_remove(&prof_tdata->lru_ql, ret.p, lru_link);
|
||||||
prof_ctx_merge(ret.p->ctx, ret.p);
|
prof_ctx_merge(ret.p->ctx, ret.p);
|
||||||
/* ret can now be re-used. */
|
/* ret can now be re-used. */
|
||||||
@ -523,8 +536,7 @@ prof_lookup(prof_bt_t *bt)
|
|||||||
ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link);
|
ql_head_insert(&prof_tdata->lru_ql, ret.p, lru_link);
|
||||||
malloc_mutex_lock(&ctx.p->lock);
|
malloc_mutex_lock(&ctx.p->lock);
|
||||||
ql_tail_insert(&ctx.p->cnts_ql, ret.p, cnts_link);
|
ql_tail_insert(&ctx.p->cnts_ql, ret.p, cnts_link);
|
||||||
if (new_ctx)
|
ctx.p->cnt_merged.curobjs--;
|
||||||
ctx.p->cnt_merged.curobjs--;
|
|
||||||
malloc_mutex_unlock(&ctx.p->lock);
|
malloc_mutex_unlock(&ctx.p->lock);
|
||||||
} else {
|
} else {
|
||||||
/* Move ret to the front of the LRU. */
|
/* Move ret to the front of the LRU. */
|
||||||
@ -650,7 +662,8 @@ prof_ctx_destroy(prof_ctx_t *ctx)
|
|||||||
assert(ctx->cnt_merged.accumobjs == 0);
|
assert(ctx->cnt_merged.accumobjs == 0);
|
||||||
assert(ctx->cnt_merged.accumbytes == 0);
|
assert(ctx->cnt_merged.accumbytes == 0);
|
||||||
/* Remove ctx from bt2ctx. */
|
/* Remove ctx from bt2ctx. */
|
||||||
ckh_remove(&bt2ctx, ctx->bt, NULL, NULL);
|
if (ckh_remove(&bt2ctx, ctx->bt, NULL, NULL))
|
||||||
|
assert(false);
|
||||||
prof_leave();
|
prof_leave();
|
||||||
/* Destroy ctx. */
|
/* Destroy ctx. */
|
||||||
malloc_mutex_unlock(&ctx->lock);
|
malloc_mutex_unlock(&ctx->lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user