class_docstr: Object for monitoring
  
  Must be child of engine
  
  Handles signal messages and watches Engine process for exiting
class_docstr_tok: ["Object","for","monitoring","Must","be","child","of","engine","Handles","signal","messages","and","watches","Engine","process","for","exiting"]
code: def pipe_handler(self, fd, events):
      self.log.debug(f"Pipe event {events}")
      self.loop.remove_handler(fd)
      try:
          fd.close()
      except BrokenPipeError:
          pass
      try:
          status = self.parent_process.wait(0)
      except psutil.TimeoutExpired:
          try:
              status = self.parent_process.status()
          except psutil.NoSuchProcess:
              status = "exited"
  
      self.log.critical(
          f"Pipe closed, parent {self.pid} has status: {status}"
      )
      self.finish()
  
imports: import asyncio
  import logging
  import os
  import pickle
  import signal
  import sys
  from subprocess import PIPE, Popen
  from threading import Thread
  import psutil
  import zmq
  from jupyter_client.session import Session
  from tornado.ioloop import IOLoop
  from traitlets.config import Config
  from zmq.eventloop.zmqstream import ZMQStream
  from ipyparallel import error, util
  from ipyparallel.util import local_logger
label_desc: Use image node_id 3 for calling the KernelNanny obj's underlying member method code with example usage: obj.pipe_handler(fd, events) without return types