Fork.py
Jump to navigation
Jump to search
#!/usr/bin/env python # # Purpose: Check function of fork() with cygwin # # $Id: fork2.py,v 1.1.1.1 2003/10/22 13:05:22 zyx Exp $ # #--------------------------------------------------------------------- """ More complex fork framework fork() and in the child use setsid() and other calls to detach from the controllling terminal """ #--------------------------------------------------------------------- import getopt import os import sys import signal import time import logging import whrandom #--------------------------------------------------------------------- __id__ = "@(#) fork2.py [1.0.0] 14/10/2003" __version__ = "1.0.0" TRUE = 1 FALSE = 0 LOGFILE = "fork2.log" PIDFILE = "fork2.pid" daemonFlg = 0 debugFlg = 0 silentFlg = 0 verboseFlg = 0 waitFlg = 0 inParent = 0 pause = 2 duration = 10 noSessions = 10 #===================================================================== def now(): return time.ctime(time.time()) # current time on the server #--------------------------------------------------------------------- def shutdown(): log.info("[fork2] Suttting down") if inParent: os.unlink(PIDFILE) sys.exit(99) #--------------------------------------------------------------------- def sigTerm(signum, frame): "SIGTERM handler" s = "[fork2] Caught SIGTERM!" print s log.info(s) shutdown() #--------------------------------------------------------------------- def readConfig(): pass #--------------------------------------------------------------------- def checkRunning(): try: pfp = open(PIDFILE, 'r') except IOError, e: pfp = 0 if pfp: line = pfp.readline() line = line.strip() serverPid = int(line) noProcess = 0 try: os.kill(serverPid, 0) except OSError, e: if e.errno == 3: noProcess = 1 else: print "kill() failed with errno %d" % e.errno sys.exit(0) if noProcess: print "[fork2] Stale server pid file!" pfp.close() os.unlink(PIDFILE) return 0 else: pfp.close() return serverPid return serverPid else: return 0 #--------------------------------------------------------------------- def writePidfile(pid): try: pfp = open(PIDFILE, 'w') except IOError, e: print "[fork2] Could not open %s" % PIDFILE sys.exit(0) print >>pfp, "%d" % pid pfp.close() return pid #--------------------------------------------------------------------- def becomeDaemon(): pid = os.fork() if pid == 0: # In child print "[fork2] fork() -> 0 (%d)" % getpid() time.sleep(1) pass elif pid == -1: # Error print "[fork2] fork() failed!" time.sleep(1) sys.exit(0) else: # In parent print "[fork2] fork() ->", getpid() time.sleep(1) sys.exit(0) time.sleep(2) os.setsid() pid = os.getpid() return pid #--------------------------------------------------------------------- def init(): global ctrlPid ctrlPid = checkRunning() if ctrlPid: print "[fork2] Server already running! (pid = %d)" % ctrlPid sys.exit(0) if daemonFlg: ctrlPid = becomeDaemon() else: ctrlPid = os.getpid() writePidfile(ctrlPid) global log log = logging.getLogger('fork2') hdlr = logging.FileHandler(LOGFILE) fmtr = logging.Formatter('%(asctime)s %(levelname)s %(message)s') hdlr.setFormatter(fmtr) log.addHandler(hdlr) log.setLevel(logging.INFO) log.info("Server started processing") global uname readConfig() if (not silentFlg): print "[fork2] Server pid is %d" % ctrlPid signal.signal(signal.SIGTERM, sigTerm) #--------------------------------------------------------------------- def terminate(): serverPid = checkRunning() if serverPid: if (not silentFlg): print "[fork2] Terminating server with pid, %d\n" % serverPid os.kill(serverPid, signal.SIGTERM) if (waitFlg): while 1: try: kill(serverPid, 0) except OSError, e: if e.errno == 3: break else: print "[server:terminate] kill() failed with errno %d" % e.errno sys.exit(0) time.sleep(1) return 0 #===================================================================== def doChild(no): global inParent inParent = 0 toGo = float(duration + 10) #os.setsid() pid = os.getpid() signal.signal(signal.SIGTERM, sigTerm) while toGo > 0.0: t = whrandom.randint(1, 1000) * 0.001 toGo -= t time.sleep(t) s = "[fork2] In child %3d [%d] - %5.2f" % (no, pid, t) log.info(s) print s #--------------------------------------------------------------------- def spawn(): global inParent inParent = 1 pids = {} for i in range(noSessions): pid = os.fork() if pid == 0: # In child doChild(i) elif pid == -1: # Error print "[fork2] fork() failed!" time.sleep(2) sys.exit(0) else: # In parent pids[i] = pid myPid = os.getpid() print "[fork2] In parent [%d]: fork() -> %d" % (myPid, pid) print "[fork2] In parent [%d]: waiting..." % myPid time.sleep(duration) print "[fork2] *** In parent [%d]: Applying SIGTERM" % myPid for i in range(noSessions): os.kill(pids[i], signal.SIGTERM) while 1: try: (pid, status) = os.wait() except OSError, e: if e.errno == 10: # No children break print "[fork2] In parent - wait() --> (PID %d, Status %d, Signal %d)" % \ (pid, ((status & 0xff00)>>8), (status & 0xff)) i -= 1 return 0 #--------------------------------------------------------------------- def main(): global debugFlg global verboseFlg global waitFlg global duration global noSessions try: opts, args = getopt.getopt(sys.argv[1:], "dD:n:TvVw?") except getopt.error, e: print __doc__ return 1 wrk = os.getcwd() base = os.path.basename(wrk) for o, a in opts: if o == '-d': debugFlg = 1 elif o == '-D': duration = int(a) elif o == '-n': noSessons = int(a) elif o == '-T': terminate() return 0 elif o == '-v': verboseFlg = 1 elif o == '-V': print "[fork2] Version: %s" % __version__ return 1 elif o == '-w': waitFlg = 1 elif o == '-?': print __doc__ return 1 print "[fork2] Working directory is %s" % os.getcwd() if args: for arg in args: print arg init() spawn() #--------------------------------------------------------------------- if __name__ == '__main__' or __name__ == sys.argv[0]: try: sys.exit(main()) except KeyboardInterrupt, e: s = "[fork2] Interrupted!" print s log.info(s) shutdown() #--------------------------------------------------------------------- """ Revision History: Date Who Description -------- --- -------------------------------------------------- 20031018 plh Initial implementation Problems to fix: To Do: Issues: """