class_docstr: Encapsulates running threads and processes of a Launchpad Program.
class_docstr_tok: ["Encapsulates","running","threads","and","processes","of","a","Launchpad","Program","."]
docstr: Stops all workers; kills them if they don't stop on time.
docstr_tok: ["Stops","all","workers",";","kills","them","if","they","do","n't","stop","on","time","."]
code: def _stop_or_kill(self):
      """Stops all workers; kills them if they don't stop on time."""
      pending_secs = self._termination_notice_secs - self._stop_counter
      if pending_secs == 0:
          if self._termination_notice_secs > 0:
              still_running = [
                  label
                  for label in self._active_workers
                  if self._active_workers[label]
              ]
              _log_and_print_with_color(
                  logging.ERROR,
                  "Worker groups that did not terminate in time: %s",
                  still_running,
              )
          self._kill()
          return
      if pending_secs >= 0:
          _log_and_print_with_color(
              logging.INFO,
              "Waiting for workers to stop for %ds.",
              pending_secs,
          )
      self._stop_counter += 1
      # Notify ThreadWorkers which registered for notifications.
      _signal_dispatcher(signal.SIGUSR1)
      for workers in self._active_workers.values():
          for worker in workers:
              if isinstance(worker, ThreadWorker):
                  # Thread workers should use wait_for_stop or register_stop_handler.
                  pass
              elif isinstance(worker, subprocess.Popen):
                  try:
                      worker.send_signal(signal.SIGTERM)
                  except psutil.NoSuchProcess:
                      pass
              else:
                  # Notify all workers running under a proxy process.
                  children = worker.children(recursive=True)
                  worker_found = False
                  for process in children:
                      try:
                          process_name = process.name()
                          if (
                              process_name != "bash"
                              and "envelope_" not in process_name
                          ):
                              worker_found = True
                              process.send_signal(signal.SIGTERM)
                      except psutil.NoSuchProcess:
                          pass
                  if not worker_found:
                      # No more workers running, so we can kill the proxy itself.
                      try:
                          worker.send_signal(signal.SIGKILL)
                      except psutil.NoSuchProcess:
                          pass
  
      if pending_secs >= 0:
          signal.alarm(1)
  
imports: import atexit
  import collections
  from concurrent import futures
  import os
  import signal
  import subprocess
  import sys
  import threading
  import time
  import traceback
  from typing import Optional, Sequence, Text
  from absl import flags
  from absl import logging
  from absl.testing import absltest
  from launchpad import flags
  import psutil
  import termcolor
label_desc: Use image node_id 13 for calling the WorkerManager obj's underlying member method code with example usage: obj._stop_or_kill() without return types