github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/rpc/pid.py (about) 1 #!/usr/bin/env python 2 3 """ An executable which proxies for a subprocess; upon a signal, it sends that 4 signal to the process identified by a pidfile. """ 5 6 import os 7 import sys 8 import signal 9 import time 10 11 12 class PidProxy: 13 pid = None 14 def __init__(self, args): 15 self.setsignals() 16 self.reaped_parent = False 17 18 try: 19 self.pidfile, cmdargs = args[1], args[2:] 20 self.command = os.path.abspath(cmdargs[0]) 21 self.cmdargs = cmdargs 22 except (ValueError, IndexError): 23 self.usage() 24 sys.exit(1) 25 26 def getpidfromfile(self): 27 try: 28 with open(self.pidfile, 'r') as f: 29 return int(f.read().strip()) 30 except: 31 return None 32 33 def go(self): 34 self.pid = os.spawnv(os.P_NOWAIT, self.command, self.cmdargs) 35 while 1: 36 time.sleep(5) 37 try: 38 self.pid = self.getpidfromfile() 39 if self.pid is None: 40 break 41 pid, sts = os.waitpid(self.pid, os.WNOHANG) 42 except OSError: 43 pid, sts = None, None 44 if pid: 45 break 46 47 def usage(self): 48 print("pidproxy.py <pidfile name> <command> [<cmdarg1> ...]") 49 50 def setsignals(self): 51 signal.signal(signal.SIGTERM, self.passtochild) 52 signal.signal(signal.SIGHUP, self.passtochild) 53 signal.signal(signal.SIGINT, self.passtochild) 54 signal.signal(signal.SIGUSR1, self.passtochild) 55 signal.signal(signal.SIGUSR2, self.passtochild) 56 signal.signal(signal.SIGQUIT, self.passtochild) 57 signal.signal(signal.SIGCHLD, self.reap) 58 59 def reap(self, sig, frame): 60 if not self.reaped_parent: 61 os.waitpid(-1, 0) 62 self.reaped_parent = True 63 return 64 try: 65 pid = self.getpidfromfile() 66 if pid is None: 67 pid = self.pid 68 _, _ = os.waitpid(pid, 0) 69 sys.exit(0) 70 except: 71 pass 72 73 def passtochild(self, sig, frame): 74 pid = self.getpidfromfile() 75 if pid is None: 76 pid = self.pid 77 os.kill(pid, sig) 78 if sig in [signal.SIGTERM, signal.SIGINT, signal.SIGQUIT]: 79 sys.exit(0) 80 81 82 def main(): 83 pp = PidProxy(sys.argv) 84 pp.go() 85 86 if __name__ == '__main__': 87 main()