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","."]
docstr: Any PIDs which exited without a graceful exit message indicates a crashed worker.
docstr_tok: ["Any","PIDs","which","exited","without","a","graceful","exit","message","indicates","a","crashed","worker","."]
code: def check_pids(self) -> None:
      """
      Any PIDs which exited without a graceful exit message indicates a crashed worker.
      """
      import psutil
  
      for pid in self.pids:
          if pid not in self.graceful_shutdowns:
              pid_ok = False
              try:
                  if psutil.Process(pid).status() not in (
                      psutil.STATUS_DEAD,
                      psutil.STATUS_STOPPED,
                      psutil.STATUS_ZOMBIE,
                  ):
                      pid_ok = True
              except psutil.NoSuchProcess:
                  pass
              if not pid_ok:
                  raise det.errors.WorkerError(
                      "Detected that worker process died."
                  )
  
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 8 for calling the PIDServer obj's underlying member method code with example usage: obj.check_pids() without return types