(Cross reference to lwt github)
I applied my use to this code sample, which will result in leaking file descriptors.
let's say you have:
#require "lwt.unix" open Lwt.Infix let echo ic oc = Lwt_io.(write_chars oc (read_chars ic)) let program = let server_address = Unix.(ADDR_INET (inet_addr_loopback, 2000)) in let other_addr = Unix.(ADDR_INET (inet_addr_loopback, 2001)) in let server = Lwt_io.establish_server server_address begin fun (tcp_ic, tcp_oc) -> Lwt_io.with_connection other_addr begin fun (nc_ic, nc_oc) -> Lwt_io.printl "Created connection" >>= fun () -> echo tcp_ic nc_oc <&> echo nc_ic tcp_oc >>= fun () -> Lwt_io.printl "finished" end |> Lwt.ignore_result end in fst (Lwt.wait ()) let () = Lwt_main.run program
and then you create a simple server using
nc -l 2001
and then run the OCaml code using utop example.ml
and then open the client
nc localhost 2000 blah blah ^c
Then, looking at the connections for port 2000 using lsof, we see
ocamlrun 71109 Edgar 6u IPv4 0x7ff3e309cb80aead 0t0 TCP 127.0.0.1:callbook (LISTEN) ocamlrun 71109 Edgar 7u IPv4 0x7ff3e309c9dc8ead 0t0 TCP 127.0.0.1:callbook->127.0.0.1:54872 (CLOSE_WAIT)
In fact, for every use of nc localhost 2000 we get the remaining CLOSE_WAIT record from using lsof.
Ultimately, this will cause the system to run out of file descriptors, which will be MOST annoyingly not a program crash, but will cause Lwt to just hang.
I canβt say that I am doing something wrong or if this is a real mistake, in any case this is a serious mistake for me, and I have run out of file descriptors within 10 hours ...
EDIT: It seems to me that the problem is that one side of the connection is closed and the other is not, I would think that with_connection should clear / close whenever both sides close, aka whenever nc_ic or nc_oc close.
EDIT II: I tried every way when I manually close the descriptors with Lwt_io.close , but I still have the CLOSE_WAIT message.
EDIT III: even Lwt_unix.close used on raw fd given with the argument fd with_connection optionally with similarly bad results.
EDIT IV: Most insidious if I use Lwt_daemon.daemonize then this problem seems to go away