(lwt githubの問題にクロス投稿)
ファイル記述子をリークするこのコード サンプルの使用法を煮詰めました。
あなたが持っていると言う:
#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
次に、次を使用して単純なサーバーを作成します。
nc -l 2001
そしてOCamlコードを起動しましょう
utop example.ml
次に、クライアントを開きます
nc localhost 2000
blah blah
^c
次に、lsof を使用してポート 2000 の接続を見ると、
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)
実際、 を使用するたびに、lsof の使用から残りのレコードをnc localhost 2000
取得します。CLOSE_WAIT
最終的に、これはシステムがファイル記述子を使い果たすことにつながります。これは、ほとんど迷惑なことにプログラムをクラッシュさせることはありませんが、Lwt がハングアップすることにつながります。
私が何か間違ったことをしているのか、それともこれが本物のバグなのかはわかりません。いずれにせよ、これは私にとって深刻なバグであり、10時間以内にファイル記述子を使い果たします...
編集:問題は、接続の一方が閉じられているが、もう一方が閉じられていないことだと思われます。with_connection
どちらかの側が閉じるたびに、別名いつでも閉じても、クリーンアップ/クローズアップnc_ic
する必要があると思いましたnc_oc
。
編集 II: で記述子を手動で閉じるあらゆる方法を試しましたLwt_io.close
が、まだ CLOSE_WAIT メッセージが表示されます。
編集 III: Lwt_unix.close
with_connection のオプションのfd
引数に与えられた raw fd で使用されても、同様の悪い結果が得られます。
編集IV:最も陰湿なのは、私が使用する場合Lwt_daemon.daemonize
、この問題は一見消えます