Max Heiber
Max Heiber

Reputation: 15562

How can I wait for multiple child processes using the OCaml Unix module?

I'm trying to parallelize work. I'm trying to have subprocesses each take a piece of the work, then wait for the work to complete from the parent process.

The following solution seems to work for small examples:

let par_iter (items: 'i list) ~(f: 'i -> unit): unit =
  let orig_pid = Unix.getpid () in
  let rec loop = function
    | [] -> ()
    | h :: t ->
      match Unix.fork () with
      | 0 -> f h
      | _ -> loop t
  in
  loop items;
  if Unix.getpid () = orig_pid then 
    List.iter items ~f:(fun _ -> ignore @@ Unix.wait ())
  else
    exit 0

Usage:

let () =
  par_iter [1; 2; 3; 4] ~f:do_something_with_an_int;

The contract of Unix.wait when there are multiple subprocesses is not very clear to me. Here I'm relying on the behavior where waiting n times will wait for all and only n subprocesses to finish.

Does this solution rely on undefined behavior? Is there an alternative way to correctly implement par_iter such that it spawns work on child processes and waits for the work to finish?

tested on OCaml 4.14.0

Upvotes: 1

Views: 144

Answers (1)

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66823

If the original parent process already had some subprocesses, this can fail. Thus, IMHO it's not usable as a general library. You should use Unix.waitpid to wait specifically for the processes you created.

Upvotes: 2

Related Questions