Lwt Unix socket client/server giving error : Unix.Unix_error(Unix.ENOENT, "connect", "")

lwt
#1

I have created a simple echo client server executable using Lwt. I am using UNIX socket as a communication mechanism between the client and the server. However, I seem to be getting the Unix.Unix_error(Unix.ENOENT, "connect", "") error. Not sure what I am missing here.

open Lwt.Infix

let socket_filename = "/tmp/client_server.sock"

let (server_is_ready, notify_server_is_ready) = Lwt.wait ()

let create_client () =
  let socket_info =
    let socket = Lwt_unix.socket PF_UNIX SOCK_STREAM 0 in
    let addr = Lwt_unix.(ADDR_UNIX socket_filename) in
    Lwt_unix.connect socket addr >>= fun _ ->
    let ic = Lwt_io.of_fd ~mode:Input socket in
    let oc = Lwt_io.of_fd ~mode:Output socket in
    Lwt.return (ic, oc)
  in
  let rec send_msg (ic, oc) =
    Lwt_io.(
      printf "Enter input: " >>= fun _ ->
      read_line stdin >>= fun line ->
      write_line oc line >>= fun _ ->
      read_line ic >>= fun line -> printlf "Server sent: %s\n" line)
    >>= fun _ -> send_msg (ic, oc)
  in
  server_is_ready >>= fun _ ->
  Lwt_io.printlf "Connecting to server on socket : %s" socket_filename
  >>= fun _ -> socket_info >>= send_msg

let create_server () =
  let echo_handler _ (ic, oc) =
    let rec echo () =
      match%lwt Lwt_io.read_line_opt ic with
      | Some s ->
          Lwt_io.(
            printlf "Client sent: %s" s >>= fun _ ->
            write_line oc s >>= fun _ -> echo ())
      | None ->
          Lwt.return_unit
    in
    Lwt_io.printl "Client connected!" >>= fun _ -> echo ()
  in
  if Sys.file_exists socket_filename then Sys.remove socket_filename ;
  let listen_addr = Lwt_unix.ADDR_UNIX socket_filename in
  let%lwt _server =
    Lwt_io.establish_server_with_client_address listen_addr echo_handler
      ~no_close:true
  in
  Lwt_io.printf "Listening for client connection on UNIX socket : %s\n"
    socket_filename
  >>= fun _ ->
  Lwt.wakeup_later notify_server_is_ready () ;
  Lwt.return_unit

let server = create_server ()

let client = create_client ()

let () = Lwt_main.run (Lwt.join [ server; client ])

The same program with ADDR_INET socket type seems to function correctly.

#2

Nothing wrong with the code, but client and server are getting started concurrently, and the server needs a few milliseconds before being able to serve requests. Slowing down the client bootstrap can fix the issue.

let client =
  let%lwt () = Lwt_unix.sleep 0.1 in
  create_client ()
#3

Indeed, it seems my client was trying to connect to server before the server was ready to listen to client connections. In my case the fix was to turn socket_info into a function, socket_info() and that seems to do it. Thanks for your help.