首页 > 解决方案 > 退出 0 不终止程序

问题描述

我正在使用 OCaml Unix 库中提供的高级网络连接功能在 OCaml 中开发客户端-服务器应用程序,遵循https://caml.inria.fr/pub/docs/oreilly-book/html/中提供的步骤书-ora187.html。这些功能是:

val open_connection : sockaddr -> in_channel * out_channel

val shutdown_connection : in_channel -> unit

val establish_server : (in_channel -> out_channel -> unit) -> sockaddr -> unit

我能够成功构建客户端和验证程序,但我无法使用exitOCaml 函数终止服务器。

我的(最小)服务器代码如下:

let handle_service ic oc =
  try while true do
        ...
        if ... then raise Finish_interaction
      done ;
  with
  | Finish_interaction -> raise Sys.Break
  | _ -> ...

let main_server serv_fun =
  if Array.length Sys.argv < 4 then ...
  else try
      let port = int_of_string Sys.argv.(1) in
      ...
      let my_address = Unix.inet_addr_loopback in
      Unix.establish_server serv_fun (Unix.ADDR_INET(my_address, port)) 
    with
    | Sys.Break -> exit 0 (* PROGRAM DOES NOT TERMINATE *)
    | _ -> ...

let go_server () = 
  Unix.handle_unix_error main_server handle_service ;;

go_server ()

我可以成功捕获Sys.Break异常,但是捕获该异常exit 0后的代码什么也不做,服务器只是继续运行并等待另一个客户端连接。

OCaml 文档对以下内容进行了说明establish_server

函数 Unix.establish_server 永远不会正常返回。

我不知道这是否意味着我永远无法在没有用户交互的情况下终止程序(例如,通过 Ctrl + C)。

简而言之,如何终止我的服务器?客户端确实在之后终止,shutdown_connection但服务器继续等待传入连接。顺便说一句,我正在使用 OCamlbuild 编译我的代码。

标签: socketsocamlclient-server

解决方案


Unix.establish_server的文档中:

为每个连接创建一个新进程

我建议打印进程 ID ( Unix.getpid ()) 以确保进程调用exit是您所期望的(父进程)。

您可以检查的另一件事是程序没有卡在at_exit回调的执行中。例如,以下程序在调用期间进入了一个无限循环exit

let () =
  at_exit (fun () -> while true do () done);
  print_endline "all is well!";
  exit 0

(可能不是您遇到的问题,但可能对未来的访问者有用)


推荐阅读