diff --git a/hosts/ocaml/lib/sx_vm.ml b/hosts/ocaml/lib/sx_vm.ml index bda0b056..c16edff8 100644 --- a/hosts/ocaml/lib/sx_vm.ml +++ b/hosts/ocaml/lib/sx_vm.ml @@ -814,12 +814,10 @@ and run vm = let resume_vm vm result = (match vm.pending_cek with | Some cek_state -> - (* Resume the suspended CEK evaluation first *) vm.pending_cek <- None; let final = Sx_ref.cek_resume cek_state result in (match Sx_runtime.get_val final (String "phase") with | String "io-suspended" -> - (* CEK suspended again — re-suspend the VM *) vm.pending_cek <- Some final; raise (VmSuspended (Sx_runtime.get_val final (String "request"), vm)) | _ -> @@ -948,12 +946,18 @@ let () = _vm_call_closure_ref := (fun cl args -> call_closure_reuse cl args) let () = _vm_suspension_to_dict := (fun exn -> match exn with | VmSuspended (request, vm) -> + (* Snapshot pending_cek NOW — a nested cek_call_or_suspend on the same VM + may overwrite it before our resume function is called. *) + let saved_cek = vm.pending_cek in let d = Hashtbl.create 3 in Hashtbl.replace d "__vm_suspended" (Bool true); Hashtbl.replace d "request" request; Hashtbl.replace d "resume" (NativeFn ("vm-resume", fun args -> match args with | [result] -> + (* Restore the saved pending_cek before resuming — it may have been + overwritten by a nested suspension on the same VM. *) + vm.pending_cek <- saved_cek; (try resume_vm vm result with exn2 -> match !_vm_suspension_to_dict exn2 with