Add low-level process support to eio_linux#435
Add low-level process support to eio_linux#435patricoferris wants to merge 13 commits intoocaml-multicore:mainfrom
Conversation
|
Just as a confirmation that using |
talex5
left a comment
There was a problem hiding this comment.
Comments in-line.
I'd still like proper clone3 support at some point, but using spawn is fine for now (just not in eio.unix).
Note that I'm changing the way FDs work a bit in #440, so you might want to rebase on that before changing anything.
|
Regarding PATH, I'd leave that out of the low-level API (which should just export what the OS provides). |
e7e4d52 to
f5aeb5d
Compare
|
W.r.t this comment:
We now vendor spawn so have a little more control over what we can do on the C-side of things, did you mean to just mark it as calling |
Yes. |
67e3ae5 to
f38ecdf
Compare
| string -> | ||
| string list -> | ||
| t | ||
| (** Spawns a subprocess. If the process has not finished when the switch is released, the process |
There was a problem hiding this comment.
This diff is looking really good! Just one thing about the documentation though: there is quite a lot of useful information in the underlying spawn ocamldoc that is worth propagating here, now that the underlying library is no longer exposed. For example, it answers: "what happens if [env] is None" in that documentation, which is quite important to know.
| has finished. *) | ||
|
|
||
| val signal : t -> int -> unit | ||
| (** [signal t s] send a signal [s] to process [t]. For example to stop a process you could use |
There was a problem hiding this comment.
| (** [signal t s] send a signal [s] to process [t]. For example to stop a process you could use | |
| (** [signal t s] sends a signal [s] to process [t]. For example, to terminate a process use |
confusingly, SIGSTOPing a process is different from SIGTERMing a process :-)
| (** [wait t] waits for the process [t] to exit. This blocks the fiber until the process | ||
| has finished. *) |
There was a problem hiding this comment.
| (** [wait t] waits for the process [t] to exit. This blocks the fiber until the process | |
| has finished. *) | |
| (** [wait t] blocks the fiber until process [t] has terminated, either by | |
| exiting or receiving a signal. *) |
|
The spawn library has a single function that does a lot of stuff, and different platforms will want to provide different features. I'm wondering if it would be better to make it more modular. The basic problem we have is that we can't call OCaml code after forking. However, we can make a list of C functions to call. Here's an experiment that defines a https://github.com/ocaml-multicore/eio/compare/main...talex5:eio:spawn?expand=1 e.g. (I put this in eio_posix, but it's demonstrating the Linux-specific open Eio.Std
module L = Eio_posix.Low_level
let () =
Eio_posix.run @@ fun _env ->
Switch.run @@ fun sw ->
let exe = L.openat ~sw ~mode:0 "/bin/ls" L.Open_flags.(rdonly + excl) in
let dir = L.openat ~sw ~mode:0 "/etc" L.Open_flags.(rdonly + directory + excl) in
let pid = L.spawn ~sw L.Fork_action.[
fchdir dir;
execat exe [| "ls"; "-l" |];
] in
traceln "spawned PID %d" pidProbably some of this could go in Eio_unix and be shared between the various backends. |
|
|
|
Cool API. The idea here is that you can have arbitrarily complicated lists of actions right? The example is a simple case that I think (at least in my mind) is easier to understand/code with something like what we have i.e. Do you think the Not quite sure where to go from here, experiment with this API first porting more of the spawn code to this modular approach? |
Yes, I'd expect the high-level API to build this up for you.
You can't do anything after
And being able to do this with
I think that would be built on top. This API is just for stuff that can only happen after forking, where we can't use OCaml.
Yes, I think so. I can try to clean it up over the next couple of days. Do you want to try putting the higher-level API on top after that? |
|
I currently have a problem where there are some syscalls I need to make after forking but before execing. This is to set up a PTY for the child process. I've got a branch using this PR at the moment, but without the PTY setup. While writing a C wrapper could work, I think @talex5's proposal would provide a good solution for this. |
Sounds good to me :)) |
|
Closing in favour of #472 :)) |
The next instalment for #330. This adds initial low-level process support to
Eio_linuxusing the spawn library which has no dependencies. I started implementing it and realised they already had, and it supports windows and has a lot of signal and error handling built-in that I otherwise would have ended up copying. It is also released under MIT so presumably we could reuse their code to avoid the dependency.I put it under
Eio_unixbecause I envisaged reusing spawn with other backends like IOCP/kqueue I think that means we have to addoptionalor something to theeio_unixlibrary?It doesn't do program resolution so I tried to do that in OCaml, I also default to the paths
[ "/usr/bin"; "/usr/local/bin" ]if we can't findPATH-- I don't know if that's reasonable. Also I'm not sure on what error we should raise if we cannot find the program.