File indexing completed on 2023-03-17 10:59:08
0001 import argparse
0002 import subprocess
0003 import signal, fcntl
0004 import sys, os, time
0005
0006
0007 stdin_ = os.dup(sys.stdin.fileno())
0008 stdout_ = os.dup(sys.stdout.fileno())
0009 sys.stdin.close()
0010 sys.stdout.close()
0011
0012 class Timeout(IOError):
0013 pass
0014
0015 def alarm_handler(signum, frame):
0016 if signum != 14: return
0017 raise Timeout("Timeout reached.")
0018
0019 signal.signal(signal.SIGALRM, alarm_handler)
0020
0021 def log(s):
0022 sys.stderr.write("watchdog: " + s + "\n");
0023 sys.stderr.flush()
0024
0025 def launch(args):
0026 fd, wd = os.pipe()
0027
0028 def preexec():
0029 os.close(fd)
0030
0031 env = os.environ
0032 env["WATCHDOG_FD"] = str(wd)
0033
0034 p = subprocess.Popen(args.pargs, preexec_fn=preexec, stdin=stdin_, stdout=stdout_)
0035 os.close(wd)
0036
0037 while True:
0038 try:
0039 signal.alarm(args.t)
0040 ch = os.read(fd, 1024)
0041 signal.alarm(0)
0042
0043 if not ch:
0044 os.close(fd)
0045 return False, p.wait()
0046
0047 log("Received: %s, timer reset." % repr(ch))
0048
0049 except Timeout as t:
0050 signal.alarm(0)
0051
0052 log("Timeout reached, taking action.")
0053
0054 if p.poll() is None:
0055 p.send_signal(args.action)
0056
0057 os.close(fd)
0058 return True, p.wait()
0059
0060 for p in open_procs_:
0061 if p.poll() is None:
0062 p.send_signal(sig)
0063
0064 def main(args):
0065 while True:
0066 killed, ret = launch(args)
0067 log("Program exitted, killed: %s, code: %d." % (killed, ret, ))
0068
0069 if killed and args.restart:
0070 log("Restarting.")
0071 continue
0072
0073 break
0074
0075
0076 parser = argparse.ArgumentParser(description="Kill/restart the child process if it doesn't out the required string.")
0077 parser.add_argument("-t", type=int, default="2", help="Timeout in seconds.")
0078 parser.add_argument("-s", type=int, default="2000", help="Signal to send.")
0079 parser.add_argument("-r", "--restart", action="store_true", default=False, help="Restart the process after killing it.")
0080 parser.add_argument("pargs", nargs=argparse.REMAINDER)
0081
0082 group = parser.add_mutually_exclusive_group()
0083 group.add_argument('--term', action='store_const', dest="action", const=signal.SIGTERM, default=signal.SIGTERM)
0084 group.add_argument('--kill', action='store_const', dest="action", const=signal.SIGKILL)
0085
0086 if __name__ == "__main__":
0087 args = parser.parse_args()
0088
0089 main(args)