Eio_main.run is like Lwt_main.run. It is typically used once in an application, at the start, and everything runs inside it. Youâd use it like this (which I would however consider bad style):
module Globals = struct
let fs = ref None
let init env =
fs := Some (Eio.Stdenv.fs env)
let load path =
Eio.Dir.load (Option.get !fs) path
let save path data =
Eio.Dir.save (Option.get !fs) path data ~create:(`Exclusive 0o666)
end
let main () =
let data = Globals.load "input.dat" in
Globals.save "output.dat" data
let () =
Eio_main.run @@ fun env ->
Globals.init env;
main ()
Whether the saved value works if you end the main-loop and then start another one would depend on the backend implementation. Itâs certainly not guaranteed to work.
If you can make a reliable version with global variables, then the capabilities arenât giving you any guarantees and could easily be added as a higher-level layer on top of a library that didnât use them.
OCaml allows any module in my dependencies to run a static initialiser, which can use Obj.magic, call C functions, etc, so we canât really guarantee anything about any non-trivial program. It would be nice if the compiler had some kind of safe mode where it would alert you about unsafe code, but it doesnât yet.
So when Eio (or any OCaml library) talks about ensuring things, it means assuming you follow some reasonable rules, even if theyâre not enforced. Roughly, this means that if you call an âunsafeâ function, you need to verify things yourself. From a capability point of view, certain extra functions in the stdlib are considered unsafe, such as open_in, which gets access to the file-system from nothing.
Note that Eio_main.run itself is not a capability-safe function, because gets access to the file-system and network from thin air. If you run the compiler in safe mode, it should therefore flag that call as something you need to audit manually. Which shouldnât be surprising - obviously you need to read your programâs main entry-point to have any idea what it will do.
To get a bound on what it can do you need to follow the env argument and see where it goes. In the example above, it gets stored in Global, so you need to audit everything that can access that. That would likely be a lot of work, which is why using global variables is generally considered bad style.
Itâs also a shame to see classes and object types appearing in what aims to be a foundational library.
Why? Eio uses objects internally, while mostly exposing a functional API. Lwt does the same thing in places (e.g. Lwt_process), and all Lwt code uses Lwt_engine in the end. It doesnât seem to cause any trouble.