Shelter imports › Eio Debugging [eio-cap-debugging]
One of the promises of Eio's capability model is an improved debugging experience. Your program must be designed in such a way as to make resources explicit. If you have a load_config function, more than likely it will need access to the file-system.
val load_config : _ Eio.Path.t -> Config.t
(** [load_config path] loads a configuration from [path].*)
Once all of your resources are explicit and threaded through your program, it becomes much easier to swap out one resource for another (provided they have the same interface).
This week I was trying to get the LIFE pipeline running in shelter. Part of that involves pulling the appropriate geospatial container image, but my code was terrifically broken, failing with what looked to me with a Docker error.
With only this clue, I knew that it was probably in the execution of some command in a child process, but which one? To trace this quickly, I could plug in a slightly different instance of the _ Eio.Process.mgr capability. Essentially unchanged from the one provided by the unix backend except that it would also print to stderr the command it was trying to run!
let debug_process_mgr (mgr : 'a Eio_unix.Process.mgr) : 'a Eio_unix.Process.mgr
=
let module D = struct
type t = unit
let spawn_unix () ~sw ?cwd ?pgid ?uid ?gid ~env ~fds ~executable args =
Eio.traceln "Spawning subprocess... %a" Fmt.(list string) args;
Eio_unix.Process.spawn_unix ~sw ?cwd ?pgid ?uid ?gid mgr ~env ~fds
~executable args
end in
let module V = Eio_unix.Process.Make_mgr (D) in
Eio.Resource.T ((), Eio_unix.Process.Pi.mgr_unix (module V))
Whist there is a fair amount of jumping through first-class-module-shaped hoops here, all I am doing is rewrapping an existing "method" to a spawn a unix child process. Then using this helper function, I can push that into my standard environment.
let env =
Eio_unix.Stdenv.with_env
~process_mgr:(debug_process_mgr env#process_mgr)
env
in
Shelter.main config (env :> _ Shelter.env) dir cmd_file
And sure enough I was querying for the Docker user before pulling the image! I hadn't run into this, as for the last while I have been using alpine and debian images that already exists locally.