Skip to content

Commit

Permalink
Rename status to await_exit
Browse files Browse the repository at this point in the history
  • Loading branch information
patricoferris committed Oct 25, 2022
1 parent 1d0f3de commit 4a37efb
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 21 deletions.
4 changes: 2 additions & 2 deletions lib_eio/process.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ let pp_status ppf = function
class virtual t = object (_ : #Generic.t)
method probe _ = None
method virtual pid : int
method virtual status : status Promise.t
method virtual await_exit : status
method virtual stop : unit
end

let pid proc = proc#pid
let status proc = proc#status
let await_exit proc = proc#await_exit
let stop proc = proc#stop

class virtual mgr = object (_ : #Generic.t)
Expand Down
4 changes: 2 additions & 2 deletions lib_eio/process.mli
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ val pp_status : Format.formatter -> status -> unit
class virtual t : object
inherit Generic.t
method virtual pid : int
method virtual status : status Promise.t
method virtual await_exit : status
method virtual stop : unit
end

val pid : #t -> int
(** The process ID *)

val status : #t -> status Promise.t
val await_exit : #t -> status
(** Checks the status of the subprocess, this will block waiting for the subprocess
to terminate or be stopped by a signal. *)

Expand Down
19 changes: 10 additions & 9 deletions lib_eio_linux/eio_linux.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1168,24 +1168,23 @@ let rec wait_for_process flags pid =

external sig_to_host_sig : int -> int = "caml_signal_to_posix_signal"

let pid_to_process close pid = object
let pid_to_process p resolver close pid = object
inherit Eio.Process.t
method pid = pid
val mutable needs_close = true
method needs_close = needs_close
method set_needs_close b = needs_close <- b
method status =
let p, r = Promise.create () in
method await_exit =
let run () =
let v = wait_for_process [] pid in
if needs_close then (close (); needs_close <- false);
match v with
| _, WEXITED i -> Promise.resolve r (Eio.Process.Exited (sig_to_host_sig i))
| _, WSIGNALED i -> Promise.resolve r (Eio.Process.Signaled (sig_to_host_sig i))
| _, WSTOPPED i -> Promise.resolve r (Eio.Process.Stopped (sig_to_host_sig i))
| _, WEXITED i -> Promise.resolve resolver (Eio.Process.Exited (sig_to_host_sig i))
| _, WSIGNALED i -> Promise.resolve resolver (Eio.Process.Signaled (sig_to_host_sig i))
| _, WSTOPPED i -> Promise.resolve resolver (Eio.Process.Stopped (sig_to_host_sig i))
in
Eio_unix.run_in_systhread run;
p
Promise.await p

method stop =
Unix.kill pid Sys.sigkill
Expand Down Expand Up @@ -1217,7 +1216,8 @@ let process_mgr = object
Unix.close stdout;
Unix.close stderr
in
let process = pid_to_process close pid in
let status, resolver = Promise.create () in
let process = pid_to_process status resolver close pid in
let cleanup () =
(* Catch if the process is already finished when trying to stop it. *)
(try process#stop with Unix.Unix_error (Unix.ESRCH, _, _) -> ());
Expand All @@ -1229,6 +1229,7 @@ let process_mgr = object

method spawn_detached ?cwd ~stdin ~stdout ~stderr cmd args =
let cwd = Option.map snd cwd in
let status, resolver = Promise.create () in
let pid =
Option.iter Sys.chdir cwd;
Unix.create_process cmd
Expand All @@ -1237,7 +1238,7 @@ let process_mgr = object
(get_fd_or_err stdout)
(get_fd_or_err stderr)
in
(pid_to_process (fun () -> ()) pid :> Eio.Process.t)
(pid_to_process status resolver (fun () -> ()) pid :> Eio.Process.t)
end

type stdenv = <
Expand Down
2 changes: 1 addition & 1 deletion lib_eio_luv/eio_luv.ml
Original file line number Diff line number Diff line change
Expand Up @@ -846,7 +846,7 @@ let process_of_handle status_promise handle = object
inherit Eio.Process.t
method stop = Luv.Process.kill handle Luv.Signal.sigkill |> or_raise
method pid = Luv.Process.pid handle
method status = status_promise
method await_exit = Promise.await status_promise
end

let get_fd_or_err flow =
Expand Down
26 changes: 19 additions & 7 deletions tests/process.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Running a program as a subprocess
# run @@ fun spawn env ->
Switch.run @@ fun sw ->
let t = spawn ~sw "echo" [ "echo"; "hello world" ] in
Promise.await (Process.status t);;
Process.await_exit t;;
hello world
- : Process.status = Eio.Process.Exited 0
```
Expand All @@ -43,7 +43,7 @@ Stopping a subprocess works and checking the status waits and reports correctly
Switch.run @@ fun sw ->
let t = spawn ~sw "sleep" [ "sleep"; "10" ] in
Process.stop t;
Promise.await (Process.status t);;
Process.await_exit t;;
- : Process.status = Eio.Process.Signaled 9
```

Expand All @@ -58,7 +58,7 @@ A switch will stop a process when it is released.
proc := Some (spawn ~sw "sleep" [ "sleep"; "10" ])
in
run ();
Promise.await @@ Process.status (Option.get !proc);;
Process.await_exit (Option.get !proc);;
- : Process.status = Eio.Process.Signaled 9
```

Expand All @@ -74,7 +74,7 @@ Passing in flows allows you to redirect the child process' stdout.
let stdout = (stdout :> Eio.Flow.sink) in
Switch.run @@ fun sw ->
let t = Eio.Process.spawn ~sw ~stdout ~stdin:env#stdin ~stderr:env#stderr process "echo" [ "echo"; "Hello" ] in
Promise.await (Process.status t)
Process.await_exit t
in
match run () with
| Exited 0 ->
Expand Down Expand Up @@ -109,7 +109,7 @@ val with_pipe_from_child :
let t =
Eio.Process.spawn ~sw ~stdout:(w :> Flow.sink) ~stdin:env#stdin ~stderr:env#stderr env#process_mgr "echo" [ "echo"; "Hello" ]
in
let status = Promise.await (Process.status t) in
let status = Process.await_exit t in
Eio.traceln "%a" Eio.Process.pp_status status;
Flow.close w;
let buff = Buffer.create 10 in
Expand All @@ -132,17 +132,29 @@ Spawning subprocesses in new domains works normally
Eio.Domain_manager.run mgr @@ fun () ->
Switch.run @@ fun sw ->
let t = spawn ~sw "echo" [ "echo"; "Hello from another domain" ] in
Promise.await (Process.status t);;
Process.await_exit t;;
Hello from another domain
- : Process.status = Eio.Process.Exited 0
```

Calling `await_exit` multiple times on the same spawn just returns the status.

```ocaml
# run @@ fun spawn env ->
Switch.run @@ fun sw ->
let t = spawn ~sw "echo" [ "echo"; "hello world" ] in
(Process.await_exit t, Process.await_exit t, Process.await_exit t);;
hello world
- : Process.status * Process.status * Process.status =
(Eio.Process.Exited 0, Eio.Process.Exited 0, Eio.Process.Exited 0)
```

The `spawn_detached` function will spawn a process without needing to provide a switch.

```ocaml
# run_detached @@ fun spawn env ->
let t = spawn "echo" [ "echo"; "hello world" ] in
Promise.await (Process.status t);;
Process.await_exit t;;
hello world
- : Process.status = Eio.Process.Exited 0
```

0 comments on commit 4a37efb

Please sign in to comment.