docs: def wait_for_processes(die_on_failure: bool = True,
                         timeout_sec: float = 1) -> None:
      """
      Wait for child processes (catalogued in :data:`processes`) to finish.
  
      If ``die_on_failure`` is ``True``, then whenever a subprocess returns
      failure, all are killed.
  
      If ``timeout_sec`` is None, the function waits for its first process to
      complete, then waits for the second, etc. So a subprocess dying does not
      trigger a full quit instantly (or potentially for ages).
  
      If ``timeout_sec`` is something else, each process is tried for that time;
      if it quits within that time, well and good (successful quit -> continue
      waiting for the others; failure -> kill everything, if ``die_on_failure``);
      if it doesn't, we try the next. That is much more responsive.
  
      """
      global processes
      global proc_args_list
      n = len(processes)
      Pool(n).map(print_lines, processes)  # in case of PIPE
      something_running = True
      while something_running:
          something_running = False
          for i, p in enumerate(processes):
              try:
                  retcode = p.wait(timeout=timeout_sec)
                  if retcode == 0:
                      log.info("Process #{} (of {}) exited cleanly", i, n)
                  if retcode != 0:
                      log.critical(
                          "Process #{} (of {}) exited with return code {} "
                          "(indicating failure); its args were: {!r}",
                          i, n, retcode, proc_args_list[i])
                      if die_on_failure:
                          log.critical("Exiting top-level process (will kill "
                                       "all other children)")
                          fail()  # exit this process, therefore kill its children  # noqa
              except TimeoutExpired:
                  something_running = True
      processes.clear()
      proc_args_list.clear()