Last active
January 20, 2022 15:05
-
-
Save matthewstory/4547282 to your computer and use it in GitHub Desktop.
Revisions
-
matthewstory revised this gist
Mar 31, 2014 . 1 changed file with 19 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,7 @@ import os import signal import sys import select import errno from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer @@ -29,7 +30,7 @@ def _gogentle(signum, frame): '''Do not throw a KeyboardInterrupt Error''' os._exit(1) # API def add(x, y): '''Add x and y''' return x + y @@ -55,7 +56,7 @@ def main(name, *argv): # fork our current process pid = os.fork() # if we are the child fork ... if 0 == pid: # die without unhandled exception for signum in ( signal.SIGINT, signal.SIGTERM, ): @@ -75,8 +76,22 @@ def main(name, *argv): # wait on the kids while len(_PIDS): # 1s timeout here means we're checking for exiting children at most # 1x per second, prevents a busy loop reads, _, _ = select.select([sys.stdin], [], [], 1) if sys.stdin in reads: # blocking, read 1 line cmd = sys.stdin.readline() # kill ourselves ... kronos will propegate if cmd.strip() == 'exit': os.kill(os.getpid(), signal.SIGTERM) # check for exited children, non-blocking while True: pid, rc = os.waitpid(-1, os.WNOHANG) if not pid: break _PIDS.remove(pid) return 0 -
matthewstory created this gist
Jan 16, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,84 @@ import os import signal import sys import errno from jsonrpclib.SimpleJSONRPCServer import SimpleJSONRPCServer # BOOK-KEEPING _PIDS = [] def _kronos(signum, frame): '''As Kronos did before us, we too may have to devour our children''' for pid in _PIDS: try: os.kill(pid, signum) except OSError, e: if e.errno == errno.ESRCH: _PIDS.remove(pid) # wait on all child processes while len(_PIDS): pid, rc = os.waitpid(-1, 0) _PIDS.remove(pid) # exit non-zero to signal abnormal termination sys.exit(1) def _gogentle(signum, frame): '''Do not throw a KeyboardInterrupt Error''' os._exit(1) # API def add(x, y): '''Add x and y''' return x + y def subtract(x, y): '''Subtract y from x''' return x - y # server def main(name, *argv): global _PIDS # JSON-RPC over HTTP on INET socket localhost:8888 # under the hood, this calls `socket.bind` then `socket.listen` s = SimpleJSONRPCServer(( argv[0], int(argv[1]), )) # register our logging math functions for fn in ( add, subtract, ): s.register_function(fn) # simple pre-fork server, fork before accept for i in range(int(argv[2])): # fork our current process pid = os.fork() # if we are the child fork ... if 0 == pid: # die without unhandled exception for signum in ( signal.SIGINT, signal.SIGTERM, ): signal.signal(signum, _gogentle) # under the hood, this calls `socket.accept` s.serve_forever() os._exit(0) # if we are the papa fork else: _PIDS.append(pid) # setup signal relaying for INT and TERM for signum in ( signal.SIGINT, signal.SIGTERM, ): signal.signal(signum, _kronos) # wait on the kids while len(_PIDS): pid, rc = os.waitpid(-1, 0) _PIDS.remove(pid) return 0 if __name__ == '__main__': sys.exit(main(*sys.argv))