[SOLVED] Catching exception of Lwt_unix.socket with Lwt.catch

lwt

#1

I have the following code that doesn’t work and I am not able to find why :

let open_socket addr port =
  Lwt.catch
    (fun () ->
      let sock = Lwt_unix.socket Lwt_unix.PF_INET Lwt_unix.SOCK_STREAM 0 in
      let sockaddr = Lwt_unix.ADDR_INET (addr, port) in
      Lwt_unix.connect sock sockaddr
      >>= fun () ->
        Lwt.return sock
    )
    (function
      | Unix.Unix_error (error, fn_name, param_name) -> Lwt.return ()
          Lwt_io.eprintf "%s %s %s : unable to open socket. Exiting..." (Unix.error_message error) fn_name param_name
          >>= fun () -> Lwt.return_nil
      | e -> Lwt.fail e
    )

The message error with Merlin is the following

This expression has type 'a list Lwt.t but an expression was expected of type Lwt_unix.file_descr Lwt.t Type 'a list is not compatible with type Lwt_unix.file_descr

I have used Lwt.catch in a previous function without problem :

let gethostbyname name =
  Lwt.catch
    (fun () ->
      Lwt_unix.gethostbyname name
      >>= fun entry ->
        let addrs = Array.to_list entry.Unix.h_addr_list in
        Lwt.return addrs
    )
    (function
      | Not_found -> lwt_print_err (name ^ ": Host not found")
        >>= fun () -> Lwt.return_nil
      | e -> Lwt.fail e
    )

#2

This error is because the “successful” evaluation in the above code produces a socket promise (expression Lwt.return sock), i.e. an Lwt_unix.file_descr Lwt.t. But the exception handler produces a list promise (Lwt.return_nil is Lwt.return []). Lists and Lwt_unix.file_descrs are incompatible types.

I don’t know exactly what you’d like to do here, but try returning options: Lwt.return (Some sock) on success, and Lwt.return_none on failure.

Also, you can write

Lwt_unix.(socket PF_INET SOCK_STREAM 0)

and I recommend trying the PPX, so you can use try%lwt and not have to write the | e -> Lwt.fail e. case


#3

Lwt.return_nil is Lwt.return []

I don’t know why I thought that Lwt.return_nul was Lwt.return ().

Lists and Lwt_unix.file_descrs are incompatible types.

Ok, now it makes sense to me.

I don’t know exactly what you’d like to do here,

The main idea is if there is a Unix exception catch it

  1. display an error message
  2. exit the program with an appropriate error code.

I recommend trying the PPX, so you can use try%lwt and not have to write the | e -> Lwt.fail e. case
ok

thanks for you help.