CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
watchdog.py
Go to the documentation of this file.
1 import argparse
2 import subprocess
3 import signal, fcntl
4 import sys, os, time
5 
6 # dup and close stdin/stdout
7 stdin_ = os.dup(sys.stdin.fileno())
8 stdout_ = os.dup(sys.stdout.fileno())
9 sys.stdin.close()
10 sys.stdout.close()
11 
12 class Timeout(IOError):
13  pass
14 
15 def alarm_handler(signum, frame):
16  if signum != 14: return
17  raise Timeout("Timeout reached.")
18 
19 signal.signal(signal.SIGALRM, alarm_handler)
20 
21 def log(s):
22  sys.stderr.write("watchdog: " + s + "\n");
23  sys.stderr.flush()
24 
25 def launch(args):
26  fd, wd = os.pipe()
27 
28  def preexec():
29  os.close(fd)
30 
31  env = os.environ
32  env["WATCHDOG_FD"] = str(wd)
33 
34  p = subprocess.Popen(args.pargs, preexec_fn=preexec, stdin=stdin_, stdout=stdout_)
35  os.close(wd)
36 
37  while True:
38  try:
39  signal.alarm(args.t)
40  ch = os.read(fd, 1024)
41  signal.alarm(0)
42 
43  if not ch:
44  os.close(fd)
45  return False, p.wait() # normal exit
46 
47  log("Received: %s, timer reset." % repr(ch))
48 
49  except Timeout as t:
50  signal.alarm(0)
51 
52  log("Timeout reached, taking action.")
53 
54  if p.poll() is None:
55  p.send_signal(args.action)
56 
57  os.close(fd)
58  return True, p.wait()
59 
60  for p in open_procs_:
61  if p.poll() is None:
62  p.send_signal(sig)
63 
64 def main(args):
65  while True:
66  killed, ret = launch(args)
67  log("Program exitted, killed: %s, code: %d." % (killed, ret, ))
68 
69  if killed and args.restart:
70  log("Restarting.")
71  continue
72 
73  break
74 
75 
76 parser = argparse.ArgumentParser(description="Kill/restart the child process if it doesn't out the required string.")
77 parser.add_argument("-t", type=int, default="2", help="Timeout in seconds.")
78 parser.add_argument("-s", type=int, default="2000", help="Signal to send.")
79 parser.add_argument("-r", "--restart", action="store_true", default=False, help="Restart the process after killing it.")
80 parser.add_argument("pargs", nargs=argparse.REMAINDER)
81 
82 group = parser.add_mutually_exclusive_group()
83 group.add_argument('--term', action='store_const', dest="action", const=signal.SIGTERM, default=signal.SIGTERM)
84 group.add_argument('--kill', action='store_const', dest="action", const=signal.SIGKILL)
85 
86 if __name__ == "__main__":
87  args = parser.parse_args()
88  #log("Args: %s." % str(args))
89  main(args)
def launch
Definition: watchdog.py:25
def log
Definition: watchdog.py:21
def alarm_handler
Definition: watchdog.py:15
def main
Definition: watchdog.py:64
Definition: main.py:1