Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:13:55

0001 import argparse
0002 import subprocess
0003 import signal, fcntl
0004 import sys, os, time
0005 
0006 # dup and close stdin/stdout
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() # normal exit
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     #log("Args: %s." % str(args))
0089     main(args)