Fix possible double free during context destruction
This commit is contained in:
@ -95,23 +95,32 @@ refcount_make_context(size_t entry_offset,
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup a #RefcountContext and free any associated resources. This also
|
||||
* causes all remaining references, both static and non-static, to be dropped
|
||||
* and the context's destroy callback to be called on each object.
|
||||
* Callback that deinits a static, but sets its static_entry field to NULL
|
||||
* first. Used in #refcount_context_destroy.
|
||||
*/
|
||||
static void deinit_static_for_context_destroy(void *obj, void *ctx_raw) {
|
||||
RefcountContext *ctx = ctx_raw;
|
||||
ENTRY->impl.static_entry = NULL;
|
||||
refcount_context_deinit_static(ctx, obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup a #RefcountContext and free any associated resources. This first
|
||||
* frees all static objects, then runs the garbage collector.
|
||||
* @param ctx The #RefcountContext
|
||||
*/
|
||||
void refcount_context_destroy(RefcountContext *ctx) {
|
||||
refcount_list_free_with_data_full(
|
||||
ctx->static_objects, refcount_context_deinit_static_as_callback, ctx,
|
||||
&ctx->alloc);
|
||||
refcount_list_free_with_data_full(ctx->static_objects,
|
||||
deinit_static_for_context_destroy, ctx,
|
||||
&ctx->alloc);
|
||||
|
||||
refcount_context_garbage_collect(ctx);
|
||||
|
||||
#ifdef REFCOUNT_HAS_THREADS
|
||||
mtx_destroy(&ctx->so_mtx);
|
||||
mtx_destroy(&ctx->gr_mtx);
|
||||
#endif
|
||||
|
||||
refcount_context_garbage_collect(ctx);
|
||||
|
||||
refcount_free(&ctx->alloc, ctx);
|
||||
}
|
||||
|
||||
@ -325,8 +334,11 @@ bool refcount_context_deinit_static(RefcountContext *ctx, void *obj) {
|
||||
ht_free(ENTRY->destructors);
|
||||
unref_weakref(ctx, ENTRY->weak_ref);
|
||||
unlock_entry_mtx(ENTRY);
|
||||
ctx->static_objects = refcount_list_remove_full(
|
||||
ctx->static_objects, ENTRY->impl.static_entry, NULL, &ctx->alloc);
|
||||
// this is set to null if we are destroying the context
|
||||
if (ENTRY->impl.static_entry) {
|
||||
ctx->static_objects = refcount_list_remove_full(
|
||||
ctx->static_objects, ENTRY->impl.static_entry, NULL, &ctx->alloc);
|
||||
}
|
||||
refcount_list_free_with_data_full(
|
||||
held_refs, refcount_context_unref_as_callback, ctx, &ctx->alloc);
|
||||
success = true;
|
||||
|
Reference in New Issue
Block a user