class_docstr: A thread that polls the state of a TPU node.
  
  When the node transitions into a TERMINAL state (PREEMPTED, TERMINATED)
  that's considered as not recoverable by the underlying infrastructure,
  it attempts to close the session, and exits the entire process if the
  session.close() stucks.
class_docstr_tok: ["A","thread","that","polls","the","state","of","a","TPU","node",".","When","the","node","transitions","into","a","TERMINAL","state","(","PREEMPTED",",","TERMINATED",")","that","'s","considered","as","not","recoverable","by","the","underlying","infrastructure",",","it","attempts","to","close","the","session",",","and","exits","the","entire","process","if","the","session.close","(",")","stucks","."]
code: def run(self):
      if not tpu_cluster_resolver.is_running_in_gce():
          logging.warning(
              "TPUPollingThread is running in a non-GCE environment, exiting..."
          )
          self._running = False
          return
  
      while self._running:
          recoverable = (
              self._cluster._cloud_tpu_client.recoverable()
          )  # pylint: disable=protected-access
          if not recoverable:
              logging.warning(
                  "TPUPollingThread found TPU %s in state %s",
                  self._cluster._tpu,
                  self._cluster._cloud_tpu_client.state(),
              )  # pylint: disable=protected-access
              os._exit(1)  # pylint: disable=protected-access
          time.sleep(self._interval)
  
file_path: tensorflow-upstream/tensorflow/python/tpu/preempted_hook.py
imports: import logging
  import os
  import threading
  import time
  from tensorflow.python.distribute.cluster_resolver import tpu_cluster_resolver
  from tensorflow.python.platform import tf_logging
  from tensorflow.python.training import session_run_hook
label_desc: Use image node_id 3 for calling the _TPUPollingThread obj's underlying member method code with example usage: obj.run() without return types