-
Notifications
You must be signed in to change notification settings - Fork 470
In dune_rpc_lwt closing the output channel should also close the input channel #7624
Description
Expected Behavior
In dune_rpc_lwt an input and output channel is created based on unix sockets backed by a single file. After the output channel is closed by passing None to the write function defined in otherlibs/dune-rpc-lwt/src/dune_rpc_lwt.ml I would expect the current/next call to Lwt_io.read* (inside the corresponding read function) to return None.
Actual Behavior
Instead an exception is raised:
Fatal error: exception Unix.Unix_error(Unix.EBADF, "check_descriptor", "")
The current workaround is to use Lwt_io.is_closed to check if the output channel has been closed before attempting to read, but this feels like it shouldn't be necessary. It's also possible to check the file descriptor associated with both the input and output channel to determine if the channel has been closed, as the file is closed when the output channel is closed.
Reproduction
- Remove the workaround mentioned above (e.g. redifine the
is_channel_closedfunction to always returnfalse) - The test
dune test otherlibs/dune-rpc-lwt/testshould now fail, though the error message is surpressed - Build and run the following program which exercises
dune_rpc_lwt(build in watch mode as it will connect to the current build server):
module Drpc_lwt = Dune_rpc_lwt.V1
module Drpc = Dune_rpc.V1
let build_dir = "_build"
let () =
let init = Drpc.Initialize.create ~id:(Drpc.Id.make (Csexp.Atom "hello")) in
let where = Drpc_lwt.Where.default ~build_dir () in
print_endline
(Printf.sprintf "Connecting to server: %s"
(Dune_rpc_private.Where.to_string where));
Lwt_main.run
(let open Lwt.Syntax in
let open Lwt.Infix in
let* chan = Drpc_lwt.connect_chan where in
Drpc_lwt.Client.connect chan init ~f:(fun client ->
print_endline "client is running";
let* request =
Drpc_lwt.Client.Versioned.prepare_request client
Drpc.Request.build_dir
>|= Result.get_ok
in
let* response =
Drpc_lwt.Client.request client request () >|= Result.get_ok
in
print_endline
(Printf.sprintf "path is: %s" (Drpc.Path.to_string_absolute response));
Lwt.return ()))After removing the workaround, its output should be:
Connecting to server: unix:path=/path/to/project/_build/.rpc/dune
client is running
path is: _build
Fatal error: exception Unix.Unix_error(Unix.EBADF, "check_descriptor", "")
Additional information
- the workaround was added in Don't attempt read from closed fd in dune_rpc_lwt #7581
- it's possible that this is a bug in
lwt_iobut it's not clear from its documentation how reading from an input channel should behave after the corresponding output channel has been closed.