def _WatchdogLoop()

in tools/android/emulator/emulated_device.py [0:0]


  def _WatchdogLoop(self, new_process_group, emu_args, emu_env, emu_wd,
                    services_dir):
    """The main loop of the watchdog process."""
    if new_process_group:
      os.setsid()
    os.closerange(-1, subprocess.MAXFD)
    watchdog_dir = None
    if 'TEST_UNDECLARED_OUTPUTS_DIR' in os.environ:
      watchdog_dir = tempfile.mkdtemp(
          dir=os.environ['TEST_UNDECLARED_OUTPUTS_DIR'])
    else:
      watchdog_dir = self._TempDir('watchdog')

    sys.stdin = open(os.devnull)
    sys.stdout = open(os.path.join(watchdog_dir, 'watchdog.out'), 'w+b', 0)
    sys.stderr = open(os.path.join(watchdog_dir, 'watchdog.err'), 'w+b', 0)

    def WaterfallForwarder():
      return self._Forward(
          services_dir, 'unix:@h2o_localhost:%s' % self.emulator_adb_port,
          'qemu:%s:sockets/h2o' % self._emulator_exec_dir)

    def WaterfallTelnetForwarder():
      return self._Forward(
          services_dir, 'qemu:%s:sockets/qemu.mgmt' % self._emulator_exec_dir,
          'tcp:localhost:%d' % self.emulator_telnet_port)

    def WaterfallPortForwarder():
      return self._StartPortForwarderServices(
          services_dir,
          'unix:@h2o_localhost:%s_xforward' % self.emulator_adb_port,
          'unix:@h2o_localhost:%s' % self.emulator_adb_port)

    waterfall_fns = [
        WaterfallForwarder, WaterfallTelnetForwarder, WaterfallPortForwarder]

    tn_pipe_services_fn = lambda: self._StartTelnetPipeServices(services_dir)

    pids_to_fns = {}
    killable = {}
    pipe_service_processes = []
    if self._use_waterfall:
      logging.info('Starting waterfall processes.')
      for fn in waterfall_fns:
        p = fn()
        pids_to_fns[p.pid] = fn
        killable[p.pid] = p
        logging.info('Started waterfall process %d', p.pid)
    else:
      logging.info('Starting pipe services.')
      pipe_service_processes = self._StartPipeServices(services_dir)
      for p in pipe_service_processes:
        killable[p.pid] = p
      tn_service_process = tn_pipe_services_fn()
      killable[tn_service_process.pid] = tn_service_process
      logging.info('Started pipe telnet forwarding service %d.',
                   tn_service_process.pid)

    if self._display:
      # Try starting the Xserver three times before giving up.
      for _ in range(3):
        try:
          self._display.Start()
          emu_env.update(self._display.environment)
          break
        except (xserver.ProcessCrashedError, xserver.TimeoutError) as e:
          logging.error('Failed to start XServer..Retrying.. %s', e)

    def WatchdogCleanup():
      logging.info('Killing emu services')
      for p in killable.values():
        try:
          p.terminate()
        except OSError as e:
          logging.info('Error killing services: %s - continue', e)
      if self._display:
        try:
          logging.info('Killing display: Xvfb, x11vnc, if they were started.')
          self._display.Kill()
          logging.info('Display terminated')
        except OSError as e:
          logging.info('Error killing display: %s - continue', e)

      if self.delete_temp_on_exit and self._emulator_tmp_dir:
        logging.info('Cleaning up data dirs.')
        print 'cleanup data dirs...'
        self.CleanUp()
        logging.info('Clean up done.')

    try:
      emu_process = common.Spawn(
          emu_args,
          exec_env=emu_env,
          exec_dir=emu_wd,
          proc_input=True,
          proc_output=self._EmulatorLogFile('wb+'))
    except (ValueError, OSError) as e:
      logging.error('Failed to start process: %s', e)
      WatchdogCleanup()
      return -1

    with open(os.path.join(self._images_dir, EMULATOR_PID), 'w') as f:
      f.write('%s' % emu_process.pid)

    while True:
      logging.info('Processes launched - babysitting!')
      dead_pid, status = os.wait()
      logging.info('Dead pid: %s - exit status %d, signal %d', dead_pid,
                   status >> 8, status & 0xF)

      if self._display.x11_pid == dead_pid:
        logging.info('XServer has died')
        WatchdogCleanup()
        return status
      elif emu_process.pid == dead_pid:
        logging.info('Emulator has died')
        WatchdogCleanup()
        return status
      elif dead_pid in [p.pid for p in pipe_service_processes]:
        try:
          logging.info('Pipe traversal daemon died - attempting to revive')
          for p in pipe_service_processes:
            try:
              del killable[p.pid]
              p.terminate()
            except OSError as e:
              # ignore.
              pass
          pipe_service_processes = self._StartPipeServices(services_dir)
          for p in pipe_service_processes:
            killable[p.pid] = p
          logging.info('restarted Pipe traversal daemon')
        except OSError as e:
          logging.info('Failed to restart pipe traversal daemon. %s', e)
      elif dead_pid in pids_to_fns:
        fn = pids_to_fns[dead_pid]
        del pids_to_fns[dead_pid]
        del killable[dead_pid]
        try:
          p = fn()
          pids_to_fns[p.pid] = fn
          killable[p.pid] = p
        except OSError as e:
          logging.info('Failed to restart process %d. %s', p.pid, e)