10249

[code]

    let rec f _ = ignore (Lwt_unix.sleep 1.0);
                  f ()
    let _ = Lwt_unix.on_signal 2 (fun _ -> print_endline "sig")
    let _ = 
      print_endline "start";
      ignore (Lwt_main.at_exit (fun () -> Lwt.return(print_endline "at_exit")));
      Lwt_main.run (f ()) 
    
[/code]

上記のように書いてみましたが、Ctrl-CでSIGINTを送っても割り込めないようです。  
きちんと割り込めるやり方か、at_exitと共通化できるようなもっと良い方法があれば教えて下さい。  
環境はOCaml4.02.1, lwt2.4.8です。


CC BY-SA 3.0
2015-05-15T15:51:51.670
10239
2015-05-16T10:16:06.147
9750
question
ocaml
Lwt_main.run実行中にシグナルを受けたら後処理をして停止したい


`Lwt_unix.sleep 1` の結果が捨てられ、 `f ()` がすぐ呼ばれています。`sleep` の前に debug print
を入れれば一秒待たずに即 `f ()` が呼ばれてしまっているのが判ると思います。

この `f` が `Lwt_main.run (f ())` の引数に出てくる所で無限ループに入ってしまうので、 プログラムを実行しても
`Lwt_main.run` には入りません。Lwt エンジンの signal handling などは `run`
内部で行われるので、このままでは(調べていませんが)うまく行くとは思いません。

まず、`Lwt_unix.sleep 1.0` の結果を `bind` (もしくは `lwt () = ... in
...`)で受けなければ、『一秒後に何かする」という動作になりません。

ちょっと試してみましたが、シグナルハンドラ内で `exit 0` すれば `at_exit` は呼ばれるようですので、次のようにするとよいのかなと思います。

[code]

    open Lwt
    
    let rec f () = bind (Lwt_unix.sleep 1.0) f
    let _ = Lwt_unix.on_signal 2 (fun _ -> exit 0)
    let _ = 
      print_endline "start";
      Lwt_main.at_exit (fun () -> Lwt.return(print_endline "at_exit"));
      Lwt_main.run (f ()) 
    
[/code]

`t Lwt.t` の値を `ignore` するのまちがいである事が多い（全てそういう訳ではないが）のでその点を気を付ければ良いと思います。


CC BY-SA 3.0
2015-05-16T03:49:53.683
10249
2015-05-16T10:16:06.147
2015-05-16T10:16:06.147
898
898
10239
answer