Стандартные библиотеки
OCaml (с модулем Sys
) и Unix
предоставляют две функции, которые должны помочь. Вероятно, в Core
есть функции эквивалентного / более высокого уровня, поскольку вы, кажется, используете его, но я не проверял это:
Unix.alarm n
повысит сигнал sigalrm
через n
секунд
Sys.signal Sys.sigalrm (Sys.Signal_handle (fun _ -> do_something()))
будет запускаться do_something()
каждый раз, когда Sys.sigalrm
повышается. Например, вызов Unix.kill
для соответствующего процесса. Кроме того, Sys.signal
возвращает старый обработчик для данного сигнала, чтобы вы могли восстановить его впоследствии.
Очень грубый и не тщательно проверенный пример будет выглядеть так:
let cmd_timeout cmd args timeout =
let pid = Unix.create_process cmd args Unix.stdin Unix.stdout Unix.stderr in
let kill _ = Unix.kill pid Sys.sigterm in
let old = Sys.signal Sys.sigalrm (Sys.Signal_handle kill) in
let _ = Unix.alarm timeout in
try
let _, res = Unix.waitpid [] pid in
(match res with
| Unix.WEXITED d ->
Printf.printf "Exited with status %d\n%!" d
| Unix.WSIGNALED d ->
Printf.printf "Signalled with %d\n%!" d
| Unix.WSTOPPED d ->
Printf.printf "Stopped with %d\n%!" d);
Sys.set_signal Sys.sigalrm old
with Unix.Unix_error(Unix.EINTR, _, _) ->
Printf.printf "Timeout!\n%!"; Sys.set_signal Sys.sigalrm old
let () = cmd_timeout "sleep" [| "sleep"; "10" |] 3 (* will timeout *)
let () = cmd_timeout "sleep" [| "sleep"; "3" |] 10 (* will exit normally *)