-
Notifications
You must be signed in to change notification settings - Fork 77
Description
Dear Eio maintainers,
I have been debugging a potentially surprising result this morning.
Consider a program with a fiber-local value i
.
utop # #require "eio_main";;
utop # open Eio;;
utop # let i: int Fiber.key = Fiber.create_key ();;
val i : int Fiber.key = <abstr>
Quite sensibly, forked fibers inherit their parent's fiber-local state:
[code listing 1]
utop # Eio_main.run (fun env ->
Switch.run (fun sw ->
Fiber.with_binding i 42 (fun () ->
Fiber.fork ~sw (fun () ->
let o = Option.map (Printf.sprintf "%d") (Fiber.get i) in
let v = Option.value o ~default:"???" in
Flow.copy_string v (Stdenv.stdout env)))));;
42- : unit = ()
Now, what happens in a domain-spawning situation? One would reasonably expect the following Eio loop, which manually spawns a domain, to bomb out, because said spawn is happening outside the purview of Eio, and so there's no mechanism to associate the "parent" fiber's context with whatever state is inside the domain, much less handle any effects!
[code listing 2]
utop # Eio_main.run (fun env ->
Switch.run (fun sw ->
Fiber.with_binding i 42 (fun () ->
Domain.join @@ Domain.spawn @@ fun () -> Fiber.get i)));;
Exception: Stdlib.Effect.Unhandled(Eio__core__Cancel.Get_context)
Of course, we have a solution for Eio and domains: Domain_manager
! Noting that the docs for Domain_manager state that "[the function passed to Domain_manager.run
] must only access thread-safe values from the calling domain", and fiber-local state is definitionally thread-safe, I would expect a combination of the behaviour of code listing 1 and code listing 2: accessing a FLS value within a domain managed by Domain_manager
should inherit the parent's value, but it does not: Instead of Some 42
, we get None
back:
[code listing 3]
utop # Eio_main.run (fun env ->
Switch.run (fun sw ->
let domain_mgr = Eio.Stdenv.domain_mgr env in
Fiber.with_binding i 42 (fun () ->
Domain_manager.run domain_mgr @@ fun () -> Fiber.get i)));;
- : int option = None
This feels like an omission to me - clearly the spawned domain is able to handle effects (we do not fail to get the context like in code listing 2), and the fact that Eio uses lambda capabilities as a core design suggests that "lexical scoping" in this manner ought to produce the value I expected. What do the Eio maintainers think? (If you feel the current behaviour is the correct one, I'd suggest at minimum being explicit about this in the docs.)
Thanks!
Nathan