Best practices for

I’m writing a program that will repeatedly spawn processes and use Lwt to asynchronously watch their stdout and wait for them to terminate. As I understand it, these watching tasks should be started with Lwt.async, but I also need to call somewhere to run the scheduler. Also, it seems like the task run by can’t terminate before the ones I started with Lwt.async (i.e. I can’t just do (Lwt_io.printl …) somewhere).

Currently I’m starting the stdout watch task with Lwt.async and the wait for termination with This works, but it doesn’t seem ideal – it means I’ll make multiple (non-nested) calls to and produces a brittle structure. Should I be doing something like calling on a promise that will never be fulfilled instead?

If you have any code examples it’ll help, but I think I know what you mean. should only be called once on the outer level, and you can choose to resolve it or run continuously from within.

So it would be something like this:

let start_watching process =
    let () = Lwt.async (some_function_of process) in
    let () = Lwt.async (another_function_of process) in

where start_watching is called repeatedly (sequentially). Currently I’m making the last call to Lwt.async in start_watching a call to instead (at least, I was at the time of the original post) but that means it gets called each time start_watching is run. I’m not sure if that’s actually an issue since the Lwt calls in each start_watching call shouldn’t overlap, but it doesn’t seem like the best way of doing things.

Rather than call Lwt.main_run again, i’d have a recursive function that’s called. I.e.

let rec main status =
  match status with
  | `Resume -> main `Resume
  | `End -> Lwt.return ()
  | `Error err -> err

let _ = (Lwt.catch (fun ()  -> main `Resume) (fun err  -> exit 0))

inside the Resume case you can then do any async stuff you want, and call main(Resume) when you’re ready to iterate again.

1 Like