class_docstr: The base class that standardizes operations over a set of processes that are launched via different mechanisms.
  
  The name ``PContext`` is intentional to disambiguate with ``torch.multiprocessing.ProcessContext``.
  
  .. warning:: stdouts and stderrs should ALWAYS be a superset of
               tee_stdouts and tee_stderrs (respectively) this is b/c
               tee is implemented as a redirect + tail -f <stdout/stderr.log>
class_docstr_tok: ["The","base","class","that","standardizes","operations","over","a","set","of","processes","that","are","launched","via","different","mechanisms",".","The","name","``","PContext","``","is","intentional","to","disambiguate","with","``","torch.multiprocessing.ProcessContext","``",".","..","warning",":",":","stdouts","and","stderrs","should","ALWAYS","be","a","superset","of","tee_stdouts","and","tee_stderrs","(","respectively",")","this","is","b\/c","tee","is","implemented","as","a","redirect","+","tail","-f","<","stdout\/stderr.log",">"]
docstr: Wait for the specified ``timeout`` seconds, polling every ``period`` seconds
  for the processes to be done. Returns ``None`` if the processes are still running
  on timeout expiry. Negative timeout values are interpreted as "wait-forever".
  A timeout value of zero simply queries the status of the processes (e.g. equivalent
  to a poll).
  
  ..note: Multiprocessing library registers SIGTERM and SIGINT signal handlers that raise
          ``SignalException`` when the signals received. It is up to the consumer of the code
          to properly handle the exception. It is important not to swallow the exception otherwise
          the process would not terminate. Example of the typical workflow can be:
  
  .. code-block:: python
      pc = start_processes(...)
      try:
          pc.wait(1)
          .. do some other work
      except SignalException as e:
          pc.shutdown(e.sigval, timeout=30)
  
  If SIGTERM or SIGINT occurs, the code above will try to shutdown child processes by propagating
  received signal. If child processes will not terminate in the timeout time, the process will send
  the SIGKILL.
code: def wait(
      self, timeout: float = -1, period: float = 1
  ) -> Optional[RunProcsResult]:
      """
      Wait for the specified ``timeout`` seconds, polling every ``period`` seconds
      for the processes to be done. Returns ``None`` if the processes are still running
      on timeout expiry. Negative timeout values are interpreted as "wait-forever".
      A timeout value of zero simply queries the status of the processes (e.g. equivalent
      to a poll).
  
      ..note: Multiprocessing library registers SIGTERM and SIGINT signal handlers that raise
              ``SignalException`` when the signals received. It is up to the consumer of the code
              to properly handle the exception. It is important not to swallow the exception otherwise
              the process would not terminate. Example of the typical workflow can be:
  
      .. code-block:: python
          pc = start_processes(...)
          try:
              pc.wait(1)
              .. do some other work
          except SignalException as e:
              pc.shutdown(e.sigval, timeout=30)
  
      If SIGTERM or SIGINT occurs, the code above will try to shutdown child processes by propagating
      received signal. If child processes will not terminate in the timeout time, the process will send
      the SIGKILL.
      """
      if timeout == 0:
          return self._poll()
  
      if timeout < 0:
          timeout = sys.maxsize
  
      expiry = time.time() + timeout
      while time.time() < expiry:
          pr = self._poll()
          if pr:
              return pr
          time.sleep(period)
  
      return None
  
imports: import abc
  import logging
  import os
  import re
  import signal
  import subprocess
  import sys
  import time
  from contextlib import nullcontext
  from dataclasses import dataclass, field
  from enum import IntFlag
  from multiprocessing import synchronize
  from types import FrameType
  from typing import Any, Callable, Dict, Optional, Set, Tuple, Union
  import torch.multiprocessing
  from torch.distributed.elastic.multiprocessing.errors import ProcessFailure, record
  from torch.distributed.elastic.multiprocessing.redirects import redirect_stderr, redirect_stdout
  from torch.distributed.elastic.multiprocessing.tail_log import TailLog
label_desc: Use image node_id 5 for calling the PContext obj's underlying member method code with example usage: obj.wait(timeout, period) and returns: None, self, pr