Skip to content

Commit

Permalink
interpreter: pop GC frames when leaving multiple :enter blocks (#57186
Browse files Browse the repository at this point in the history
)

Resolves #56062
  • Loading branch information
topolarity authored Jan 28, 2025
1 parent 575d8e8 commit 7a97bc9
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
8 changes: 7 additions & 1 deletion src/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,9 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip,
s->locals[jl_source_nslots(s->src) + ip] = jl_box_ulong(jl_excstack_state(ct));
if (jl_enternode_scope(stmt)) {
jl_value_t *scope = eval_value(jl_enternode_scope(stmt), s);
// GC preserve the scope, since it is not rooted in the `jl_handler_t *`
// and may be removed from jl_current_task by any nested block and then
// replaced later
JL_GC_PUSH1(&scope);
ct->scope = scope;
if (!jl_setjmp(__eh.eh_ctx, 1)) {
Expand Down Expand Up @@ -606,8 +609,11 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip,
// equivalent to jl_pop_handler(hand_n_leave), longjmping
// to the :enter code above instead, which handles cleanup
jl_handler_t *eh = ct->eh;
while (--hand_n_leave > 0)
while (--hand_n_leave > 0) {
// pop GC frames for any skipped handlers
ct->gcstack = eh->gcstack;
eh = eh->prev;
}
// leave happens during normal control flow, but we must
// longjmp to pop the eval_body call for each enter.
s->continue_at = next_ip;
Expand Down
13 changes: 13 additions & 0 deletions test/scopedvalues.jl
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,16 @@ end
@test Core.current_scope() === nothing
end
nothrow_scope()

# https://github.com/JuliaLang/julia/issues/56062
@testset "issue #56062" begin
ts = Int[]
try
@with begin
return
end
catch err
finally
push!(ts, 2)
end
end

0 comments on commit 7a97bc9

Please sign in to comment.