From 244c66933402ac616ad10871950d6486503fa9fc Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 5 Apr 2026 00:59:45 +0000 Subject: [PATCH] =?UTF-8?q?Revert=20cek=5Frun=20import=20patch=20=E2=80=94?= =?UTF-8?q?=20caused=20infinite=20CEK=20loop=20on=20server?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cek_run import handling (resume after hook loads library) caused cek_step_loop to infinite-loop during aser page rendering. Root cause not yet identified — the resumed CEK state never reaches terminal. Reverted to original cek_run that throws "IO suspension in non-IO context". The 4 server startup errors are harmless (files load partially, all needed symbols available via other paths). Import hook re-entry guard and debug logging retained for future work. Co-Authored-By: Claude Opus 4.6 (1M context) --- hosts/ocaml/bin/sx_server.ml | 24 ++++++++++++++++++------ hosts/ocaml/lib/sx_ref.ml | 15 +-------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/hosts/ocaml/bin/sx_server.ml b/hosts/ocaml/bin/sx_server.ml index 57d42780..74e9469c 100644 --- a/hosts/ocaml/bin/sx_server.ml +++ b/hosts/ocaml/bin/sx_server.ml @@ -794,16 +794,28 @@ let () = Hashtbl.replace _shared_vm_globals name v) (* Import hook — resolves (import ...) suspensions inside eval_expr/cek_run. - Loads the .sx file for the library, registers it, and returns true. *) + Loads the .sx file for the library, registers it, and returns true. + Re-entry guard prevents infinite loops from circular or failing imports. *) +let _loading_libs : (string, bool) Hashtbl.t = Hashtbl.create 8 let () = Sx_types._import_hook := Some (fun lib_spec -> if Sx_types.sx_truthy (Sx_ref.library_loaded_p lib_spec) then true - else match resolve_library_path lib_spec with + else + let key = Sx_types.inspect lib_spec in + if Hashtbl.mem _loading_libs key then false (* already loading — break cycle *) + else begin + Hashtbl.replace _loading_libs key true; + let result = match resolve_library_path lib_spec with | Some path -> - (try load_library_file path; - true - with _ -> false) - | None -> false) + (try load_library_file path; true + with e -> + Printf.eprintf "[import-hook] FAIL %s from %s: %s\n%!" + key path (Printexc.to_string e); + false) + | None -> false in + (* Don't remove — keep as "attempted" guard to prevent retries *) + result + end) let make_server_env () = let env = make_env () in diff --git a/hosts/ocaml/lib/sx_ref.ml b/hosts/ocaml/lib/sx_ref.ml index a80fcd2d..f3ed5e23 100644 --- a/hosts/ocaml/lib/sx_ref.ml +++ b/hosts/ocaml/lib/sx_ref.ml @@ -488,20 +488,7 @@ and cek_step_loop state = (* cek-run *) and cek_run state = - (let rec run s = - let final = cek_step_loop s in - if sx_truthy (cek_suspended_p final) then begin - let request = cek_io_request final in - let op = match request with Dict d -> (match Hashtbl.find_opt d "op" with Some (String s) -> s | _ -> "") | _ -> "" in - if op = "import" then - let lib_spec = match request with Dict d -> (match Hashtbl.find_opt d "library" with Some v -> v | _ -> Nil) | _ -> Nil in - let resolved = sx_truthy (library_loaded_p lib_spec) || - (match !_import_hook with Some hook -> hook lib_spec | None -> false) in - if resolved then run (cek_resume final Nil) - else raise (Eval_error "IO suspension in non-IO context") - else raise (Eval_error "IO suspension in non-IO context") - end else cek_value final - in run state) + (let final = (cek_step_loop (state)) in (if sx_truthy ((cek_suspended_p (final))) then (raise (Eval_error (value_to_str (String "IO suspension in non-IO context")))) else (cek_value (final)))) (* cek-resume *) and cek_resume suspended_state result' =