Skip to content

Commit

Permalink
Convert Eio.Process to FCMs
Browse files Browse the repository at this point in the history
  • Loading branch information
patricoferris committed Aug 16, 2023
1 parent e948fa7 commit 24ab674
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 114 deletions.
2 changes: 1 addition & 1 deletion lib_eio/eio.ml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ module Stdenv = struct
let stdout (t : <stdout : _ Flow.sink; ..>) = t#stdout
let stderr (t : <stderr : _ Flow.sink; ..>) = t#stderr
let net (t : <net : _ Net.t; ..>) = t#net
let process_mgr (t : <process_mgr : #Process.mgr; ..>) = t#process_mgr
let process_mgr (t : <process_mgr : _ Process.mgr; ..>) = t#process_mgr
let domain_mgr (t : <domain_mgr : #Domain_manager.t; ..>) = t#domain_mgr
let clock (t : <clock : #Time.clock; ..>) = t#clock
let mono_clock (t : <mono_clock : #Time.Mono.t; ..>) = t#mono_clock
Expand Down
2 changes: 1 addition & 1 deletion lib_eio/eio.mli
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ module Stdenv : sig
To use this, see {!Process}.
*)

val process_mgr : <process_mgr : #Process.mgr as 'a; ..> -> 'a
val process_mgr : <process_mgr : _ Process.mgr as 'a; ..> -> 'a
(** [process_mgr t] allows you to manage child processes. *)

(** {1 Domains (using multiple CPU cores)}
Expand Down
58 changes: 38 additions & 20 deletions lib_eio/process.ml
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,36 @@ let await_exn ?(is_success = Int.equal 0) proc =

let signal proc = proc#signal

class virtual mgr = object
method virtual pipe :
sw:Switch.t ->
[Flow.source_ty | Resource.close_ty] r * [Flow.sink_ty | Resource.close_ty] r

method virtual spawn :
sw:Switch.t ->
?cwd:Fs.dir_ty Path.t ->
?stdin:Flow.source_ty r ->
?stdout:Flow.sink_ty r ->
?stderr:Flow.sink_ty r ->
?env:string array ->
?executable:string ->
string list ->
t
type mgr_ty = [`Mgr]
type 'a mgr = ([> mgr_ty] as 'a) r

module Pi = struct
module type MGR = sig
val pipe :
sw:Switch.t ->
[Flow.source_ty | Resource.close_ty] r * [Flow.sink_ty | Resource.close_ty] r

val spawn :
sw:Switch.t ->
?cwd:Fs.dir_ty Path.t ->
?stdin:Flow.source_ty r ->
?stdout:Flow.sink_ty r ->
?stderr:Flow.sink_ty r ->
?env:string array ->
?executable:string ->
string list ->
t

type t
end

type (_, _, _) Resource.pi +=
| Proc : ('t, (module MGR with type t = 't), [> mgr_ty]) Resource.pi

let mgr (type t) (module X : MGR with type t = t) =
Resource.handler [
H (Proc, (module X));
]
end

let bad_char = function
Expand All @@ -77,16 +92,17 @@ let pp_arg f x =

let pp_args = Fmt.hbox (Fmt.list ~sep:Fmt.sp pp_arg)

let spawn ~sw (t:#mgr) ?cwd ?stdin ?stdout ?stderr ?env ?executable args =
t#spawn ~sw
let spawn ~sw (Resource.T (_, ops)) ?cwd ?stdin ?stdout ?stderr ?env ?executable args =
let module X = (val (Resource.get ops Pi.Proc)) in
X.spawn ~sw
?cwd:(cwd :> Fs.dir_ty Path.t option)
?env
?executable args
?stdin:(stdin :> Flow.source_ty r option)
?stdout:(stdout :> Flow.sink_ty r option)
?stderr:(stderr :> Flow.sink_ty r option)

let run (t:#mgr) ?cwd ?stdin ?stdout ?stderr ?(is_success = Int.equal 0) ?env ?executable args =
let run t ?cwd ?stdin ?stdout ?stderr ?(is_success = Int.equal 0) ?env ?executable args =
Switch.run @@ fun sw ->
let child = spawn ~sw t ?cwd ?stdin ?stdout ?stderr ?env ?executable args in
match await child with
Expand All @@ -95,9 +111,11 @@ let run (t:#mgr) ?cwd ?stdin ?stdout ?stderr ?(is_success = Int.equal 0) ?env ?e
let ex = err (Child_error status) in
raise (Exn.add_context ex "running command: %a" pp_args args)

let pipe ~sw (t:#mgr) = t#pipe ~sw
let pipe ~sw (Resource.T (_, ops)) =
let module X = (val (Resource.get ops Pi.Proc)) in
X.pipe ~sw

let parse_out (t:#mgr) parse ?cwd ?stdin ?stderr ?is_success ?env ?executable args =
let parse_out t parse ?cwd ?stdin ?stderr ?is_success ?env ?executable args =
Switch.run @@ fun sw ->
let r, w = pipe t ~sw in
try
Expand Down
54 changes: 34 additions & 20 deletions lib_eio/process.mli
Original file line number Diff line number Diff line change
Expand Up @@ -68,27 +68,41 @@ val signal : #t -> int -> unit

(** {2 Spawning processes} *)

class virtual mgr : object
method virtual pipe :
sw:Switch.t ->
[Flow.source_ty | Resource.close_ty] r * [Flow.sink_ty | Resource.close_ty] r

method virtual spawn :
sw:Switch.t ->
?cwd:Fs.dir_ty Path.t ->
?stdin:Flow.source_ty r ->
?stdout:Flow.sink_ty r ->
?stderr:Flow.sink_ty r ->
?env:string array ->
?executable:string ->
string list ->
t
end
type mgr_ty = [`Mgr]
type 'a mgr = ([> mgr_ty] as 'a) r
(** A process manager capable of spawning new processes. *)

module Pi : sig
module type MGR = sig
val pipe :
sw:Switch.t ->
[Flow.source_ty | Resource.close_ty] r * [Flow.sink_ty | Resource.close_ty] r

val spawn :
sw:Switch.t ->
?cwd:Fs.dir_ty Path.t ->
?stdin:Flow.source_ty r ->
?stdout:Flow.sink_ty r ->
?stderr:Flow.sink_ty r ->
?env:string array ->
?executable:string ->
string list ->
t

type t
end

type (_, _, _) Resource.pi +=
| Proc : ('t, (module MGR with type t = 't), [> mgr_ty]) Resource.pi

val mgr :
(module MGR with type t = 't) ->
('t, mgr_ty) Resource.handler
end

val spawn :
sw:Switch.t ->
#mgr ->
_ mgr ->
?cwd:Fs.dir_ty Path.t ->
?stdin:_ Flow.source ->
?stdout:_ Flow.sink ->
Expand All @@ -114,7 +128,7 @@ val spawn :
searching $PATH for it if necessary. *)

val run :
#mgr ->
_ mgr ->
?cwd:_ Path.t ->
?stdin:_ Flow.source ->
?stdout:_ Flow.sink ->
Expand All @@ -132,7 +146,7 @@ val run :
Note: If [spawn] needed to create extra fibers to copy [stdin], etc, then it also waits for those to finish. *)

val parse_out :
#mgr ->
_ mgr ->
'a Buf_read.parser ->
?cwd:_ Path.t ->
?stdin:_ Flow.source ->
Expand All @@ -154,7 +168,7 @@ val parse_out :

(** {2 Pipes} *)

val pipe : sw:Switch.t -> #mgr -> [Flow.source_ty | Resource.close_ty] r * [Flow.sink_ty | Resource.close_ty] r
val pipe : sw:Switch.t -> _ mgr -> [Flow.source_ty | Resource.close_ty] r * [Flow.sink_ty | Resource.close_ty] r
(** [pipe ~sw mgr] creates a pipe backed by the OS.
The flows can be used by {!spawn} without the need for extra fibers to copy the data.
Expand Down
2 changes: 1 addition & 1 deletion lib_eio/unix/eio_unix.ml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ module Stdenv = struct
stderr : sink_ty r;
net : [`Unix | `Generic] Eio.Net.ty r;
domain_mgr : Eio.Domain_manager.t;
process_mgr : Process.mgr;
process_mgr : Process.mgr_ty Process.mgr;
clock : Eio.Time.clock;
mono_clock : Eio.Time.Mono.t;
fs : Eio.Fs.dir_ty Eio.Path.t;
Expand Down
2 changes: 1 addition & 1 deletion lib_eio/unix/eio_unix.mli
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ module Stdenv : sig
stderr : sink_ty r;
net : [`Unix | `Generic] Eio.Net.ty r;
domain_mgr : Eio.Domain_manager.t;
process_mgr : Process.mgr;
process_mgr : Process.mgr_ty Process.mgr;
clock : Eio.Time.clock;
mono_clock : Eio.Time.Mono.t;
fs : Eio.Fs.dir_ty Eio.Path.t;
Expand Down
50 changes: 39 additions & 11 deletions lib_eio/unix/process.ml
Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,49 @@ let get_env = function
| Some e -> e
| None -> Unix.environment ()

class virtual mgr = object (self)
inherit Eio.Process.mgr
type mgr_ty = [`Mgr_unix | Eio.Process.mgr_ty]
type 'a mgr = ([> mgr_ty] as 'a) r

method pipe ~sw =
(Private.pipe sw :> ([Eio.Resource.close_ty | Eio.Flow.source_ty] r *
[Eio.Resource.close_ty | Eio.Flow.sink_ty] r))
module Pi = struct
module type MGR = sig
include Eio.Process.Pi.MGR

val spawn_unix :
sw:Switch.t ->
?cwd:Eio.Fs.dir_ty Eio.Path.t ->
env:string array ->
fds:(int * Fd.t * Fork_action.blocking) list ->
executable:string ->
string list ->
Eio.Process.t
end

type (_, _, _) Eio.Resource.pi +=
| Proc_unix : ('t, (module MGR with type t = 't), [> mgr_ty]) Eio.Resource.pi

let mgr (type t) (module X : MGR with type t = t) =
Eio.Resource.handler [
H (Eio.Process.Pi.Proc, (module X));
H (Proc_unix, (module X));
]
end

method virtual spawn_unix :
module Make_proc (X : sig
val spawn_unix :
sw:Switch.t ->
?cwd:Eio.Fs.dir_ty Eio.Path.t ->
env:string array ->
fds:(int * Fd.t * Fork_action.blocking) list ->
executable:string ->
string list ->
Eio.Process.t
end) = struct
type t = unit
let pipe ~sw =
(Private.pipe sw :> ([Eio.Resource.close_ty | Eio.Flow.source_ty] r *
[Eio.Resource.close_ty | Eio.Flow.sink_ty] r))

method spawn ~sw ?cwd ?stdin ?stdout ?stderr ?env ?executable args =
let spawn ~sw ?cwd ?stdin ?stdout ?stderr ?env ?executable args =
let executable = get_executable executable ~args in
let env = get_env env in
with_close_list @@ fun to_close ->
Expand All @@ -97,13 +123,15 @@ class virtual mgr = object (self)
1, stdout_fd, `Blocking;
2, stderr_fd, `Blocking;
] in
self#spawn_unix ~sw ?cwd ~env ~fds ~executable args
end
X.spawn_unix ~sw ?cwd ~env ~fds ~executable args

let spawn_unix ~sw (mgr:#mgr) ?cwd ~fds ?env ?executable args =
let spawn_unix = X.spawn_unix
end
let spawn_unix ~sw (Eio.Resource.T (_, ops)) ?cwd ~fds ?env ?executable args =
let module X = (val (Eio.Resource.get ops Pi.Proc_unix)) in
let executable = get_executable executable ~args in
let env = get_env env in
mgr#spawn_unix ~sw ?cwd ~fds ~env ~executable args
X.spawn_unix ~sw ?cwd ~fds ~env ~executable args

let sigchld = Eio.Condition.create ()

Expand Down
47 changes: 27 additions & 20 deletions lib_eio/unix/process.mli
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,45 @@

open Eio.Std

class virtual mgr : object
inherit Eio.Process.mgr
type mgr_ty = [`Mgr_unix | Eio.Process.mgr_ty]
type 'a mgr = ([> mgr_ty] as 'a) r

method pipe :
sw:Switch.t ->
[Eio.Flow.source_ty | Eio.Resource.close_ty] r * [Eio.Flow.sink_ty | Eio.Resource.close_ty] r
module Pi : sig
module type MGR = sig
include Eio.Process.Pi.MGR

val spawn_unix :
sw:Switch.t ->
?cwd:Eio.Fs.dir_ty Eio.Path.t ->
env:string array ->
fds:(int * Fd.t * Fork_action.blocking) list ->
executable:string ->
string list ->
Eio.Process.t
end

method virtual spawn_unix :
type (_, _, _) Eio.Resource.pi +=
| Proc_unix : ('t, (module MGR with type t = 't), [> mgr_ty]) Eio.Resource.pi

val mgr :
(module MGR with type t = 't) ->
('t, mgr_ty) Eio.Resource.handler
end

module Make_proc (_ : sig
val spawn_unix :
sw:Switch.t ->
?cwd:Eio.Fs.dir_ty Eio.Path.t ->
env:string array ->
fds:(int * Fd.t * Fork_action.blocking) list ->
executable:string ->
string list ->
Eio.Process.t

method spawn :
sw:Switch.t ->
?cwd:Eio.Fs.dir_ty Eio.Path.t ->
?stdin:Eio.Flow.source_ty r ->
?stdout:Eio.Flow.sink_ty r ->
?stderr:Eio.Flow.sink_ty r ->
?env:string array ->
?executable:string ->
string list ->
Eio.Process.t
(** The default implementation uses {!spawn_unix}. *)
end
end) : Pi.MGR with type t = unit

val spawn_unix :
sw:Switch.t ->
#mgr ->
_ mgr ->
?cwd:Eio.Fs.dir_ty Eio.Path.t ->
fds:(int * Fd.t * Fork_action.blocking) list ->
?env:string array ->
Expand Down
Loading

0 comments on commit 24ab674

Please sign in to comment.