class_docstr: TFX infra validator executor.
class_docstr_tok: ["TFX","infra","validator","executor","."]
docstr: Install graceful shutdown behavior.
  
  Caveat: InfraValidator currently only recognizes SIGTERM signal as a
  graceful shutdown. Furthermore, SIGTERM can be handled only if the executor
  is running on the MainThread (the thread that runs the python interpreter)
  due to the limitation of Python API.
  
  When the executor is running on Kubernetes, SIGTERM is a standard way to
  signal the graceful shutdown. Python default behavior for receiving SIGTERM
  is to terminate the process without raising any exception. By registering a
  handler that raises on signal, we can effectively transform the signal to an
  exception, and we can reuse our cleanup code inside "except" or "finally"
  block during the grace period.
  
  When the executor is run by the local Beam DirectRunner, the executor thread
  is one of the worker threads (not a MainThread) therefore SIGTERM cannot
  be recognized. If either of MainThread or worker thread receives SIGTERM,
  executor will die immediately without grace period.
  
  Even if the executor fails to shutdown gracefully, external resources that
  are created by model server runner can be cleaned up if the platform
  supports such mechanism (e.g. activeDeadlineSeconds in Kubernetes).
code: def _InstallGracefulShutdownHandler(self):
      # pylint: disable=g-doc-return-or-yield
      """Install graceful shutdown behavior.
  
      Caveat: InfraValidator currently only recognizes SIGTERM signal as a
      graceful shutdown. Furthermore, SIGTERM can be handled only if the executor
      is running on the MainThread (the thread that runs the python interpreter)
      due to the limitation of Python API.
  
      When the executor is running on Kubernetes, SIGTERM is a standard way to
      signal the graceful shutdown. Python default behavior for receiving SIGTERM
      is to terminate the process without raising any exception. By registering a
      handler that raises on signal, we can effectively transform the signal to an
      exception, and we can reuse our cleanup code inside "except" or "finally"
      block during the grace period.
  
      When the executor is run by the local Beam DirectRunner, the executor thread
      is one of the worker threads (not a MainThread) therefore SIGTERM cannot
      be recognized. If either of MainThread or worker thread receives SIGTERM,
      executor will die immediately without grace period.
  
      Even if the executor fails to shutdown gracefully, external resources that
      are created by model server runner can be cleaned up if the platform
      supports such mechanism (e.g. activeDeadlineSeconds in Kubernetes).
      """
  
      def _handler(signum, frame):
          del frame  # Unused.
          raise error_types.GracefulShutdown(
              "Got signal {}.".format(signum)
          )
  
      try:
          old_handler = signal.signal(signal.SIGTERM, _handler)
      except ValueError:
          # If current thread is not a MainThread, it is not allowed to register
          # the signal handler (ValueError raised).
          logging.info(
              "Unable to register signal handler for non-MainThread "
              "(name=%s). SIGTERM will not be handled.",
              threading.current_thread().name,
          )
          old_handler = None
  
      try:
          yield
      finally:
          self._Cleanup()
          if old_handler:
              signal.signal(signal.SIGTERM, old_handler)
  
imports: import contextlib
  import functools
  import os
  import signal
  import threading
  import time
  from typing import Any, Dict, List, Optional
  from absl import logging
  from tfx import types
  from tfx.components.infra_validator import error_types
  from tfx.components.infra_validator import request_builder
  from tfx.components.infra_validator import serving_bins
  from tfx.components.infra_validator import types
  from tfx.components.infra_validator.model_server_runners import kubernetes_runner
  from tfx.components.infra_validator.model_server_runners import local_docker_runner
  from tfx.dsl.components.base import base_executor
  from tfx.proto import infra_validator_pb2
  from tfx.types import artifact_utils
  from tfx.types import standard_component_specs
  from tfx.utils import io_utils
  from tfx.utils import path_utils
  from tfx.utils import proto_utils
  from tfx.utils.model_paths import tf_serving_flavor
  from tensorflow_serving.apis import classification_pb2
  from tensorflow_serving.apis import predict_pb2
  from tensorflow_serving.apis import prediction_log_pb2
  from tensorflow_serving.apis import regression_pb2
label_desc: Use image node_id 5 for calling the Executor obj's underlying member method code with example usage: obj._InstallGracefulShutdownHandler() without return types