class_docstr: PIDServer tracks PIDs reported by a set of pid_clients which connect to it.
  
  PIDServer.run() will return when all pid_clients have reported a graceful shutdown and have
  exited, or it will raise an exception if any pids disappear without reporting a graceful
  shutdown.
  
  PIDServer lets an sshd-based launch layer keep track of its worker processes, even when the
  worker processes aren't proper child processes.
class_docstr_tok: ["PIDServer","tracks","PIDs","reported","by","a","set","of","pid_clients","which","connect","to","it",".","PIDServer.run","(",")","will","return","when","all","pid_clients","have","reported","a","graceful","shutdown","and","have","exited",",","or","it","will","raise","an","exception","if","any","pids","disappear","without","reporting","a","graceful","shutdown",".","PIDServer","lets","an","sshd-based","launch","layer","keep","track","of","its","worker","processes",",","even","when","the","worker","processes","are","n't","proper","child","processes","."]
code: def run_subprocess(
      self,
      cmd: List[str],
      on_fail: Optional[signal.Signals] = None,
      on_exit: Optional[signal.Signals] = None,
      grace_period: int = 3,
      signal_children: bool = False,
  ) -> int:
      p = subprocess.Popen(cmd)
  
      class HealthCheckFail(Exception):
          def __init__(self, exit_code: int):
              super().__init__()
              self.exit_code = exit_code
  
      def health_check() -> None:
          ret = p.poll()
          if ret is not None:
              raise HealthCheckFail(ret)
  
      with det.util.forward_signals(p, signal_children=signal_children):
          try:
              self.run(health_check)
          except HealthCheckFail as e:
              return e.exit_code or 77
          except det.errors.WorkerError:
              # Worker failed.
              if on_fail is not None:
                  # Let things finish logging, exiting on their own, etc.
                  time.sleep(grace_period)
                  if signal_children:
                      det.util.signal_process_tree(p, on_fail)
                  p.send_signal(on_fail)
                  if on_fail != signal.SIGKILL:
                      try:
                          return p.wait(timeout=10) or 78
                      except subprocess.TimeoutExpired:
                          logger.error(
                              f"killing worker which didn't exit after {on_fail.name}"
                          )
                          p.send_signal(signal.SIGKILL)
              return p.wait() or 79
  
          # All workers exited normally.
          if on_exit is not None:
              time.sleep(grace_period)
              p.send_signal(on_exit)
              if on_exit != signal.SIGKILL:
                  try:
                      return p.wait(timeout=10)
                  except subprocess.TimeoutExpired:
                      logger.error(
                          f"killing worker which didn't exit after {on_exit.name}"
                      )
                      p.send_signal(signal.SIGKILL)
          return p.wait()
  
imports: import logging
  import os
  import selectors
  import signal
  import socket
  import subprocess
  import time
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
  import determined
label_desc: Use image node_id 10 for calling the PIDServer obj's underlying member method code with example usage: obj.run_subprocess(cmd, on_fail, on_exit, grace_period, signal_children) and returns: p, unknown, unknown, p, unknown