/usr/share/pyshared/albatross/fcgispawn.py is in python-albatross 1.36-5.5.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | #
# Copyright 2006 by Object Craft P/L, Melbourne, Australia.
#
# LICENCE - see LICENCE file distributed with this software for details.
#
import os
import sys
import getopt
import socket
import time
import errno
import signal
ourname = os.path.basename(sys.argv[0])
workers = {}
class Worker:
def __init__(self, sock, *cmdline):
self.pid = os.fork()
self.cmd = cmdline[0]
if self.pid:
workers[self.pid] = self
self.start_time = time.time()
else:
time.sleep(0.1)
os.dup2(sock.fileno(), 0)
os.close(1)
sock.close()
os.execl(self.cmd, *cmdline)
def reap(self, status):
aborted = False
if os.WIFSIGNALED(status):
if os.WTERMSIG(status) != signal.SIGTERM:
print '%s: %s: pid %s killed by signal %s' %\
(ourname, self.cmd, self.pid, os.WTERMSIG(status))
aborted = True
elif os.WIFEXITED(status):
if os.WEXITSTATUS(status):
print '%s: %s: pid %s exited with status %s' %\
(ourname, self.cmd, self.pid, os.WEXITSTATUS(status))
aborted = True
if aborted and (time.time() - self.start_time) < 2:
print '%s restarting too rapidly' % (self.cmd)
else:
del workers[self.pid]
def reap_children():
try:
pid, status = os.wait()
except OSError, (eno, estr):
if eno == errno.ECHILD:
sys.exit('No more children, exiting')
if eno != errno.EINTR:
raise
else:
try:
workers[pid].reap(status)
except KeyError:
pass
run = True
def stop(*args):
print "HERE"
run = False
def spawn(sock, nprocs, *cmd):
signal.signal(signal.SIGINT, stop)
signal.signal(signal.SIGTERM, stop)
while run:
while len(workers) < nprocs:
Worker(sock, *cmd)
reap_children()
def get_unix_socket(arg):
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.bind(arg)
s.listen(8)
return s
def get_inet_socket(arg):
try:
addr, port = arg.split(':', 1)
except ValueError:
addr, port = '', arg
try:
port = int(port)
except ValueError:
usage()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((addr, port))
s.listen(8)
return s
def usage():
sys.exit('''\
Usage: %s [opts] <fcgiapp>
-u, --unix= Unix domain socket address (path)
-i, --inet= Internet domain socket (port, or addr:port)
-m, --min= Prespawn minimum
-M, --max= Maximum processes
-I, --idle= Max idle time''' % ourname)
def fatal(msg):
sys.exit('%s: %s' % (ourname, msg))
if __name__ == '__main__':
sock = None
nprocs = 2
optlist, args = getopt.getopt(sys.argv[1:], 'd:i:n:u:',
['dir=', 'unix=', 'inet=', 'min=', 'max=', 'idle='])
for opt, arg in optlist:
if opt in ('-d', '--dir'):
os.chdir(arg)
if opt in ('-u', '--unix'):
if sock:
fatal('-u and -i are mutually exclusive')
sock = get_unix_socket(arg)
elif opt in ('-i', '--inet'):
if sock:
fatal('-u and -i are mutually exclusive')
sock = get_inet_socket(arg)
elif opt in ('-n', '--nprocs'):
try:
nprocs = int(arg)
except ValueError, e:
fatal('-n: %s' % e)
elif opt == '?':
usage()
if not sock:
fatal('no listen socket specified?')
if not args:
fatal('no command specified')
spawn(sock, nprocs, *args)
|