let exec ?(bin="") argl =
  let command = (bin, Array.of_list argl) in
  let process = Lwt_process.open_process_full command in
  wrap_deferred ~on_exn:(fun e ->
      Log.(s "Tarminating process: " % parens (
          quote bin % s ", " % OCaml.list quote argl) @ verbose);
      process#terminate; 
      Lwt.ignore_result process#close; 
      `Process (`Exec (bin, argl), `Exn e))
    Lwt.(fun () ->
        Lwt_list.map_p Lwt_io.read
          [process#stdout; process#stderr; ]
        >>= fun output_2list ->
        process#close >>= fun status ->
        return (status, output_2list))
  >>= fun (ret, output_2list) ->
  let code =
    match ret with
    | Lwt_unix.WEXITED n ->   (`Exited n)
    | Lwt_unix.WSIGNALED n -> (`Signaled n)
    | Lwt_unix.WSTOPPED n ->  (`Stopped n)
  in
  begin match output_2list with
  | [out; err] -> return (out, err, code)
  | _ -> assert false
  end