GC+context: Fix GC reaching some invalid pointers / dead objects

This commit is contained in:
Laria 2022-07-14 21:13:34 +02:00
parent 7c63a6b189
commit 3fcf4f4c49

View file

@ -589,21 +589,22 @@ apfl_ctx_new(struct apfl_allocator base_allocator)
return NULL;
}
apfl_gc_init(&ctx->gc, base_allocator, get_roots, ctx);
// It's important that we initialize all these before initializing the
// garbage collector, otherwise it might try to follow invalid pointers.
ctx->error_handler = NULL;
ctx->panic_callback = NULL;
ctx->panic_callback_data = NULL;
ctx->toplevel_stack = apfl_stack_new();
ctx->call_stack = call_stack_new();
ctx->globals = NULL;
ctx->iterative_runners = iterative_runners_list_new();
apfl_gc_init(&ctx->gc, base_allocator, get_roots, ctx);
if ((ctx->globals = apfl_scope_new(&ctx->gc)) == NULL) {
goto error;
}
ctx->error_handler = NULL;
ctx->panic_callback = NULL;
ctx->panic_callback_data = NULL;
ctx->iterative_runners = iterative_runners_list_new();
if (!init_globals(ctx)) {
goto error;
}
@ -663,9 +664,34 @@ find_iterative_runner(apfl_ctx ctx, apfl_iterative_runner runner, size_t *index)
return false;
}
bool
apfl_ctx_register_iterative_runner(apfl_ctx ctx, apfl_iterative_runner runner)
struct iterative_runner_tmproot_data {
struct gc *gc;
bool ok;
};
static void
ctx_register_iterative_runner_tmproot(void *opaque, struct gc_object *object)
{
struct iterative_runner_tmproot_data *data = opaque;
if (!data->ok) {
return;
}
data->ok = apfl_gc_tmproot_add(data->gc, object);
}
static bool
ctx_register_iterative_runner_inner(apfl_ctx ctx, apfl_iterative_runner runner)
{
struct iterative_runner_tmproot_data data = {
.gc = &ctx->gc,
.ok = true
};
apfl_iterative_runner_visit_gc_objects(runner, ctx_register_iterative_runner_tmproot, &data);
if (!data.ok) {
return false;
}
if (find_iterative_runner(ctx, runner, NULL)) {
return true;
}
@ -681,6 +707,15 @@ apfl_ctx_register_iterative_runner(apfl_ctx ctx, apfl_iterative_runner runner)
);
}
bool
apfl_ctx_register_iterative_runner(apfl_ctx ctx, apfl_iterative_runner runner)
{
size_t tmproots = apfl_gc_tmproots_begin(&ctx->gc);
bool out = ctx_register_iterative_runner_inner(ctx, runner);
apfl_gc_tmproots_restore(&ctx->gc, tmproots);
return out;
}
void
apfl_ctx_unregister_iterative_runner(apfl_ctx ctx, apfl_iterative_runner runner)
{