def watchdog_run(conf, args):
	signal.signal(signal.SIGUSR2, watchdog_run_pong)
	proc = proc_poller = None
	proc_pongs = 0

	while True:
		if not proc:
			r, w = os.pipe()
			proc_opts = list(args) + [
				'--parent-pid-do-not-use', 'w{}-{}'.format(os.getpid(), w) ]
			proc = subprocess.Popen(self_exec_cmd(*proc_opts))
			os.close(w)
			assert os.read(r, 1) == '!'
			proc_poller = select.epoll()
			proc_poller.register(r, select.EPOLLHUP)
			watchdog_run.ping_last_ts = ts_ping = ts_timeout = None

		ts = mono_time()

		if ts_timeout and ts >= ts_timeout:
			proc_running, proc_restart = proc.poll() is None, proc_pongs >= 2
			log.debug(
				'wd: !!! sending exit-signal (to %s, running: %s, restart: %s, pongs: %s) !!!',
				proc.pid, proc_running, proc_restart, proc_pongs )
			if proc:
				if proc_running:
					try:
						proc.send_signal(signal.SIGALRM)
						if not proc_poller.poll(min(conf.watchdog_ping_timeout, 3)):
							log.debug('wd: killing stuck pid %s', proc.pid)
							proc.send_signal(signal.SIGCONT)
							proc.kill()
					except (__HOLE__, IOError) as err:
						if err.errno not in [errno.ESRCH, errno.EINTR]: raise
				proc.wait()
				proc, proc_pongs = None, 0
			if not proc_restart:
				log.error( 'wd: main process failed without enough'
					' pongs from it, not restarting to avoid endless restart-loop' )
				return 1
			continue

		ts_ping_last = getattr(watchdog_run, 'ping_last_ts', None)
		if ts_ping_last:
			watchdog_run.ping_last_ts = None
			proc_pongs += 1
			ts_timeout = ts_ping_last + conf.watchdog_ping_timeout
			if not ts_ping: ts_ping = ts_ping_last + conf.watchdog_ping_interval

		if ts_ping and ts >= ts_ping:
			log.debug('wd: sending ping (to %s)', proc.pid)
			try: proc.send_signal(signal.SIGUSR2)
			except OSError as err:
				if err.errno != errno.ESRCH: raise
				continue
			while ts_ping <= ts: ts_ping = ts_ping + conf.watchdog_ping_interval

		deadline = min(ts_ping or ts_timeout, ts_timeout or ts_ping)\
			if ts_ping or ts_timeout else (ts + conf.watchdog_ping_interval)
		try: proc_poller.poll(max(0.1, deadline - ts))
		except IOError: pass
		if proc.poll() is not None:
			err = proc.wait()
			if err != 0: proc = None
			log.debug( 'wd: detected process exit'
				' (code: %s), %s', err, 'exiting' if proc else 'restarting it' )
			if proc: return err
dataset/ETHPy150Open mk-fg/pulseaudio-mixer-cli/pa-mixer-mk2.py/watchdog_run