Capnp-rpc Fiber.fork with expect tests

Hello,
My client code has expect tests following this function.

let  new_cluster no_of_nodes env =

   let listen_address = [`TCP ("127.0.0.1", 8888) ;`TCP ("127.0.0.1", 7777)] in
   Eio.Switch.run (fun sw ->
   let list_of_servers =
   (* Lwt_eio.with_event_loop ~clock:(Eio.Stdenv.clock env) @@ fun () -> *)

   let rec loop_while la p i  =

    if i < no_of_nodes then(
      let path = ( "/Users/anu/Documents/rays/raft1/raft" ^ ( Int.to_string i) ^ ".cap") in

      Fiber.fork ~sw ( fun () ->
          let () = start_server ~sw env#net env  (List.nth la i) path
              in ()
      );
      Printf.printf "\nNode %d\n" i;
      loop_while la ( p @ [path]) (i + 1)
    )
    else p
   in
   loop_while listen_address [] 0
   in
	 {
      mu        =   Eio.Mutex.create();
      no_of_nodes = no_of_nodes;
      server_cap_files = list_of_servers;
	 }
  )


And my server is this.

let start_server ~sw net _env listen_address file_path =
  let fmt = " %s" ^^ "" in
  Printf.printf fmt
    (match listen_address with
                     | `TCP (_s,i) ->  Int.to_string i
                     |  _ -> "Ok" );

  let config = Capnp_rpc_unix.Vat_config.create ~secret_key ~net listen_address in
  let service_id = Capnp_rpc_unix.Vat_config.derived_id config "main" in
  let restore = Capnp_rpc_net.Restorer.single service_id (StatusOp.status_local) in
  let vat = Capnp_rpc_unix.serve ~sw ~restore config in
  

  (match Capnp_rpc_unix.Cap_file.save_service vat service_id file_path with
  | Error `Msg m -> failwith m
  | Ok () ->
    traceln "Server running. Connect using %S." file_path;
  );
  Fiber.await_cancel()

I believe this should be restructured because the Fiber.await_cancel() is awaiting a signal.
So the code blocks.

How should I restructure my expect tests (which I haven’t shown ) so that they execute. Fiber.fork() is probably in the wrong place ?.
dune test --auto-promote blocks. There are 2 servers now.

Lwt_eio.with_event_loop was used initially for direct calls without cap files as the functions use Lwt and Eio. But at this point I don’t see the relation to the blocked server. Once the tests execute I may need that event loop. Not sure.

Thanks.

I think I may have an answer even though I am not sure how to test with multiple nodes properly.

I moved the switch sw inside the test and now pass it to new_cluster. This at least executes the test.

let%expect_test "Send Replicated Log" =
  Eio_main.run @@ fun env ->
  Eio.Switch.run (fun sw ->
    let new_cluster = new_cluster 2 env sw in
    (* Rest of the code *)
 )

The servers are up and client code seems to call with an unrelated failure.
The Lwt_eio.with_event_loop is required when I call the RPC function from the client shown below

let run_client env _service =
  Lwt_eio.with_event_loop ~clock:(Eio.Stdenv.clock env) @@ fun () ->
  Capability.with_ref (getstatus_local()) @@ fun local -> getstatus local

let connect net env uri sw =
  (* Switch.run @@ fun sw -> *)

  let client_vat = Capnp_rpc_unix.client_only_vat ~sw net in
  let sr = Capnp_rpc_unix.Vat.import_exn client_vat uri in
  Capnp_rpc_unix.with_cap_exn sr (run_client env)


Does this look like appropriate code ?

(* CR expect_test_collector: This test expectation appears to contain a backtrace.
This is strongly discouraged as backtraces are fragile.
Please change this test to not include a backtrace. *)
(“Fun.Finally_raised: Failure("Attempt to change ref-count (to rc=0-1) on freed resource Status(rc=0)")”)
Raised at Stdlib.failwith in file “stdlib.ml”, line 29, characters 17-33
Called from Capnp_rpc_proto__Core_types.Make.ref_counted#update_rc in file “capnp-rpc/proto/core_types.ml”, line 65, characters 21-51
Called from Stdlib__Fun.protect.finally_no_exn in file “fun.ml”, line 30, characters 8-18
Re-raised at Stdlib__Fun.protect.finally_no_exn in file “fun.ml”, line 32, characters 6-57
Called from Stdlib__Fun.protect in file “fun.ml”, line 35, characters 14-31
Called from Stdlib__Fun.protect in file “fun.ml”, line 34, characters 8-15
Re-raised at Stdlib__Fun.protect in file “fun.ml”, line 39, characters 6-52
Called from Eio__core__Switch.run_internal in file “lib_eio/core/switch.ml”, line 133, characters 8-12
Re-raised at Eio__core__Switch.maybe_raise_exs in file “lib_eio/core/switch.ml”, line 119, characters 21-56
Called from Eio__core__Switch.run_internal in file “lib_eio/core/switch.ml”, line 149, characters 4-21
Called from Eio__core__Cancel.with_cc in file “lib_eio/core/cancel.ml”, line 118, characters 8-12
Re-raised at Eio__core__Cancel.with_cc in file “lib_eio/core/cancel.ml”, line 120, characters 50-58
Called from Stdlib__Fun.protect in file “fun.ml”, line 34, characters 8-15
Re-raised at Stdlib__Fun.protect in file “fun.ml”, line 39, characters 6-52
Called from Raft1__Test_replicated_log.(fun).loop_while in file “raft1/test/test_replicated_log.ml”, lines 78-81, characters 14-46
Called from Raft1__Test_replicated_log.(fun) in file “raft1/test/test_replicated_log.ml”, line 84, characters 2-14
Called from Eio__core__Switch.run_internal in file “lib_eio/core/switch.ml”, line 133, characters 8-12
Re-raised at Eio__core__Switch.maybe_raise_exs in file “lib_eio/core/switch.ml”, line 119, characters 21-56
Called from Eio__core__Switch.run_internal in file “lib_eio/core/switch.ml”, line 149, characters 4-21
Called from Eio__core__Cancel.with_cc in file “lib_eio/core/cancel.ml”, line 118, characters 8-12
Re-raised at Eio__core__Cancel.with_cc in file “lib_eio/core/cancel.ml”, line 120, characters 50-58
Called from Eio_posix__Sched.with_op in file “lib_eio_posix/sched.ml”, line 318, characters 8-12
Re-raised at Eio_posix__Sched.with_op in file “lib_eio_posix/sched.ml”, line 324, characters 4-12
Called from Eio_posix__Sched.run.(fun) in file “lib_eio_posix/sched.ml”, line 386, characters 29-47
Called from Eio_unix__Thread_pool.run in file “lib_eio/unix/thread_pool.ml”, line 108, characters 8-13
Re-raised at Eio_unix__Thread_pool.run in file “lib_eio/unix/thread_pool.ml”, line 113, characters 4-39
Re-raised at Eio_posix__Sched.run.fork.(fun) in file “lib_eio_posix/sched.ml”, line 342, characters 12-76
Called from Stdlib__Fun.protect in file “fun.ml”, line 34, characters 8-15
Re-raised at Stdlib__Fun.protect in file “fun.ml”, line 39, characters 6-52
Called from Eio_posix__Sched.run in file “lib_eio_posix/sched.ml”, lines 381-388, characters 4-9
Called from Eio_posix__Sched.with_sched in file “lib_eio_posix/sched.ml”, line 258, characters 8-12
Re-raised at Eio_posix__Sched.with_sched in file “lib_eio_posix/sched.ml”, line 263, characters 4-39
Called from Ppx_expect_runtime__Test_block.Configured.dump_backtrace in file “runtime/test_block.ml”, line 142, characters 10-28

Trailing output

Connecting to tcp:127.0.0.1:8888… +Server running. Connect using “/Users/anu/Documents/rays/raft1/raft0.cap”.
+Server running. Connect using “/Users/anu/Documents/rays/raft1/raft1.cap”.
OK
Connecting to tcp:127.0.0.1:7777… OK
8888
Node 0
7777
Node 1
Ok Ok
|}]