def post_fork_hook(self): """ Called in each child process, prior to starting the actual wsgi server, to drop privileges. """ drop_privileges(self.conf.get('user', 'swift'), call_setsid=False)
def post_fork_hook(self): """ Called in each child process, prior to starting the actual wsgi server, to drop privileges. """ drop_privileges(self.conf.get("user", "swift"), call_setsid=False)
def do_bind_ports(self): """ Bind the one listen socket for this strategy and drop privileges (since the parent process will never need to bind again). """ try: self.sock = get_socket(self.conf) except ConfigFilePortError: msg = 'bind_port wasn\'t properly set in the config file. ' \ 'It must be explicitly set to a valid port number.' return msg drop_privileges(self.conf.get('user', 'swift'))
def setup(self, **kwargs): utils.validate_configuration() utils.drop_privileges(self.daemon.conf.get('user', 'swift')) utils.capture_stdio(self.logger, **kwargs) def kill_children(*args): self.running = False self.logger.info('SIGTERM received') signal.signal(signal.SIGTERM, signal.SIG_IGN) os.killpg(0, signal.SIGTERM) os._exit(0) signal.signal(signal.SIGTERM, kill_children) self.running = True
def run(self, once=False, **kwargs): """Run the daemon""" utils.validate_configuration() utils.drop_privileges(self.conf.get('user', 'swift')) utils.capture_stdio(self.logger, **kwargs) def kill_children(*args): signal.signal(signal.SIGTERM, signal.SIG_IGN) os.killpg(0, signal.SIGTERM) sys.exit() signal.signal(signal.SIGTERM, kill_children) if once: self.run_once(**kwargs) else: self.run_forever(**kwargs)
def test_drop_privileges(self): user = getuser() # over-ride os with mock required_func_calls = ("setgid", "setuid", "setsid", "chdir", "umask") utils.os = MockOs(called_funcs=required_func_calls) # exercise the code utils.drop_privileges(user) for func in required_func_calls: self.assert_(utils.os.called_funcs[func]) # reset; test same args, OSError trying to get session leader utils.os = MockOs(called_funcs=required_func_calls, raise_funcs=("setsid",)) for func in required_func_calls: self.assertFalse(utils.os.called_funcs.get(func, False)) utils.drop_privileges(user) for func in required_func_calls: self.assert_(utils.os.called_funcs[func])
def filler(args, q): if args.verbose: level = logging.DEBUG else: level = logging.INFO logging.basicConfig(level=level) policy = POLICIES[args.policy_index] conf = { 'devices': args.devices, 'mount_check': False, } df_mgr = DiskFileRouter(conf, logging)[policy] if args.user: drop_privileges(args.user) while True: df_spec = q.get() if df_spec is None: return df = df_mgr.get_diskfile( df_spec['device'], df_spec['part'], df_spec['account'], df_spec['container'], df_spec['obj'], POLICIES[df_spec['policy_index']], ) with df.create() as writer: timestamp = Timestamp(time.time()) remaining = args.size hasher = hashlib.md5() while remaining > 0: chunk = BUFFER[:remaining] writer.write(chunk) hasher.update(chunk) remaining -= len(chunk) metadata = { 'ETag': hasher.hexdigest(), 'X-Timestamp': timestamp.internal, 'Content-Length': str(args.size), } writer.put(metadata) writer.commit(timestamp) logging.debug( 'created ' '/%(device)s/%(part)s/%(account)s/%(container)s/%(obj)s', df_spec)
def test_drop_privileges(self): user = getuser() # over-ride os with mock required_func_calls = ('setgid', 'setuid', 'setsid', 'chdir', 'umask') utils.os = MockOs(called_funcs=required_func_calls) # exercise the code utils.drop_privileges(user) for func in required_func_calls: self.assert_(utils.os.called_funcs[func]) # reset; test same args, OSError trying to get session leader utils.os = MockOs(called_funcs=required_func_calls, raise_funcs=('setsid',)) for func in required_func_calls: self.assertFalse(utils.os.called_funcs.get(func, False)) utils.drop_privileges(user) for func in required_func_calls: self.assert_(utils.os.called_funcs[func])
def main(args): parser = argparse.ArgumentParser( description='Relink and cleanup objects to increase partition power') parser.add_argument('action', choices=['relink', 'cleanup']) parser.add_argument( 'conf_file', nargs='?', help=('Path to config file with [object-relinker] section')) parser.add_argument('--swift-dir', default=None, dest='swift_dir', help='Path to swift directory') parser.add_argument('--devices', default=None, dest='devices', help='Path to swift device directory') parser.add_argument('--user', default=None, dest='user', help='Drop privileges to this user before relinking') parser.add_argument('--device', default=None, dest='device', help='Device name to relink (default: all)') parser.add_argument('--skip-mount-check', default=False, help='Don\'t test if disk is mounted', action="store_true", dest='skip_mount_check') parser.add_argument('--files-per-second', default=None, type=non_negative_float, dest='files_per_second', help='Used to limit I/O. Zero implies no limit ' '(default: no limit).') parser.add_argument('--logfile', default=None, dest='logfile', help='Set log file name. Ignored if using conf_file.') parser.add_argument('--debug', default=False, action='store_true', help='Enable debug mode') args = parser.parse_args(args) if args.conf_file: conf = readconf(args.conf_file, 'object-relinker') if args.debug: conf['log_level'] = 'DEBUG' user = args.user or conf.get('user') if user: drop_privileges(user) logger = get_logger(conf) else: conf = {'log_level': 'DEBUG' if args.debug else 'INFO'} if args.user: # Drop privs before creating log file drop_privileges(args.user) conf['user'] = args.user logging.basicConfig( format='%(message)s', level=logging.DEBUG if args.debug else logging.INFO, filename=args.logfile) logger = logging.getLogger() conf.update({ 'swift_dir': args.swift_dir or conf.get('swift_dir', '/etc/swift'), 'devices': args.devices or conf.get('devices', '/srv/node'), 'mount_check': (config_true_value(conf.get('mount_check', 'true')) and not args.skip_mount_check), 'files_per_second': (args.files_per_second if args.files_per_second is not None else non_negative_float(conf.get('files_per_second', '0'))), }) if args.action == 'relink': return relink(conf, logger, device=args.device) if args.action == 'cleanup': return cleanup(conf, logger, device=args.device)
:param conf_file: Path to paste.deploy style configuration file :param app_section: App name from conf file to load config from """ # Load configuration, Set logger and Load request processor try: (app, conf, logger, log_name) = \ init_request_processor(conf_file, app_section, *args, **kwargs) except ConfigFileError, e: print e return # bind to address and port sock = get_socket(conf, default_port=kwargs.get('default_port', 8080)) # remaining tasks should not require elevated privileges drop_privileges(conf.get('user', 'swift')) # set utils.FALLOCATE_RESERVE if desired reserve = int(conf.get('fallocate_reserve', 0)) if reserve > 0: utils.FALLOCATE_RESERVE = reserve # redirect errors to logger and close stdio capture_stdio(logger) def run_server(max_clients): wsgi.HttpProtocol.default_request_version = "HTTP/1.0" # Turn off logging requests by the underlying WSGI software. wsgi.HttpProtocol.log_request = lambda *a: None # Redirect logging other messages by the underlying WSGI software. wsgi.HttpProtocol.log_message = \ lambda s, f, *a: logger.error('ERROR WSGI: ' + f % a) wsgi.WRITE_TIMEOUT = int(conf.get('client_timeout') or 60)
def main(args): parser = argparse.ArgumentParser( description='Relink and cleanup objects to increase partition power') parser.add_argument('action', choices=['relink', 'cleanup']) parser.add_argument( 'conf_file', nargs='?', help=('Path to config file with [object-relinker] section')) parser.add_argument('--swift-dir', default=None, dest='swift_dir', help='Path to swift directory') parser.add_argument( '--policy', default=[], dest='policies', action='append', type=policy, help='Policy to relink; may specify multiple (default: all)') parser.add_argument('--devices', default=None, dest='devices', help='Path to swift device directory') parser.add_argument('--user', default=None, dest='user', help='Drop privileges to this user before relinking') parser.add_argument('--device', default=[], dest='device_list', action='append', help='Device name to relink (default: all)') parser.add_argument('--partition', '-p', default=[], dest='partitions', type=non_negative_int, action='append', help='Partition to relink (default: all)') parser.add_argument('--skip-mount-check', default=False, help='Don\'t test if disk is mounted', action="store_true", dest='skip_mount_check') parser.add_argument('--files-per-second', default=None, type=non_negative_float, dest='files_per_second', help='Used to limit I/O. Zero implies no limit ' '(default: no limit).') parser.add_argument('--stats-interval', default=None, type=non_negative_float, dest='stats_interval', help='Emit stats to recon roughly every N seconds. ' '(default: %d).' % DEFAULT_STATS_INTERVAL) parser.add_argument('--workers', default=None, type=auto_or_int, help=('Process devices across N workers ' '(default: one worker per device)')) parser.add_argument('--logfile', default=None, dest='logfile', help='Set log file name. Ignored if using conf_file.') parser.add_argument('--debug', default=False, action='store_true', help='Enable debug mode') args = parser.parse_args(args) hubs.use_hub(get_hub()) if args.conf_file: conf = readconf(args.conf_file, 'object-relinker') if args.debug: conf['log_level'] = 'DEBUG' user = args.user or conf.get('user') if user: drop_privileges(user) logger = get_logger(conf) else: conf = {'log_level': 'DEBUG' if args.debug else 'INFO'} if args.user: # Drop privs before creating log file drop_privileges(args.user) conf['user'] = args.user logging.basicConfig( format='%(message)s', level=logging.DEBUG if args.debug else logging.INFO, filename=args.logfile) logger = logging.getLogger() conf.update({ 'swift_dir': args.swift_dir or conf.get('swift_dir', '/etc/swift'), 'devices': args.devices or conf.get('devices', '/srv/node'), 'mount_check': (config_true_value(conf.get('mount_check', 'true')) and not args.skip_mount_check), 'files_per_second': (args.files_per_second if args.files_per_second is not None else non_negative_float(conf.get('files_per_second', '0'))), 'policies': set(args.policies) or POLICIES, 'partitions': set(args.partitions), 'workers': config_auto_int_value( conf.get('workers') if args.workers is None else args.workers, 'auto'), 'recon_cache_path': conf.get('recon_cache_path', DEFAULT_RECON_CACHE_PATH), 'stats_interval': non_negative_float( args.stats_interval or conf.get('stats_interval', DEFAULT_STATS_INTERVAL)), }) return parallel_process(args.action == 'cleanup', conf, logger, args.device_list)
def run_wsgi(conf_path, app_section, *args, **kwargs): """ Runs the server using the specified number of workers. :param conf_path: Path to paste.deploy style configuration file/directory :param app_section: App name from conf file to load config from :returns: 0 if successful, nonzero otherwise """ # Load configuration, Set logger and Load request processor try: (conf, logger, log_name) = \ _initrp(conf_path, app_section, *args, **kwargs) except ConfigFileError as e: print e return 1 # bind to address and port sock = get_socket(conf, default_port=kwargs.get('default_port', 8080)) # remaining tasks should not require elevated privileges drop_privileges(conf.get('user', 'swift')) # Ensure the configuration and application can be loaded before proceeding. global_conf = {'log_name': log_name} if 'global_conf_callback' in kwargs: kwargs['global_conf_callback'](conf, global_conf) loadapp(conf_path, global_conf=global_conf) # set utils.FALLOCATE_RESERVE if desired reserve = int(conf.get('fallocate_reserve', 0)) if reserve > 0: utils.FALLOCATE_RESERVE = reserve # redirect errors to logger and close stdio capture_stdio(logger) worker_count = config_auto_int_value(conf.get('workers'), CPU_COUNT) # Useful for profiling [no forks]. if worker_count == 0: run_server(conf, logger, sock, global_conf=global_conf) return 0 def kill_children(*args): """Kills the entire process group.""" logger.error('SIGTERM received') signal.signal(signal.SIGTERM, signal.SIG_IGN) running[0] = False os.killpg(0, signal.SIGTERM) def hup(*args): """Shuts down the server, but allows running requests to complete""" logger.error('SIGHUP received') signal.signal(signal.SIGHUP, signal.SIG_IGN) running[0] = False running = [True] signal.signal(signal.SIGTERM, kill_children) signal.signal(signal.SIGHUP, hup) children = [] while running[0]: while len(children) < worker_count: pid = os.fork() if pid == 0: signal.signal(signal.SIGHUP, signal.SIG_DFL) signal.signal(signal.SIGTERM, signal.SIG_DFL) run_server(conf, logger, sock) logger.notice('Child %d exiting normally' % os.getpid()) return 0 else: logger.notice('Started child %s' % pid) children.append(pid) try: pid, status = os.wait() if os.WIFEXITED(status) or os.WIFSIGNALED(status): logger.error('Removing dead child %s' % pid) children.remove(pid) except OSError as err: if err.errno not in (errno.EINTR, errno.ECHILD): raise except KeyboardInterrupt: logger.notice('User quit') break greenio.shutdown_safe(sock) sock.close() logger.notice('Exited') return 0
sys.exit(1) # redirect standard file descriptors sys.stdout.flush() sys.stderr.flush() stin = file(self.stdin, 'r') stout = file(self.stdout, 'a+') sterr = file(self.stderr, 'a+', 0) os.dup2(stin.fileno(), sys.stdin.fileno()) os.dup2(stout.fileno(), sys.stdout.fileno()) os.dup2(sterr.fileno(), sys.stderr.fileno()) # write pidfile atexit.register(self.delpid) pid = str(os.getpid()) file(self.pidfile, 'w+').write("%s\n" % pid) drop_privileges(user=self.uid) def delpid(self): """Remove pid file""" os.remove(self.pidfile) def start(self, *args, **kw): """ Start the daemon """ # Check for a pidfile to see if the daemon already runs try: pidfile = file(self.pidfile, 'r') pid = int(pidfile.read().strip()) pidfile.close() except IOError:
:param conf_file: Path to paste.deploy style configuration file :param app_section: App name from conf file to load config from """ # Load configuration, Set logger and Load request processor try: (app, conf, logger, log_name) = \ init_request_processor(conf_file, app_section, *args, **kwargs) except ConfigFileError, e: print e return # bind to address and port sock = get_socket(conf, default_port=kwargs.get('default_port', 8080)) # remaining tasks should not require elevated privileges drop_privileges(conf.get('user', 'swift')) # redirect errors to logger and close stdio capture_stdio(logger) def run_server(): wsgi.HttpProtocol.default_request_version = "HTTP/1.0" # Turn off logging requests by the underlying WSGI software. wsgi.HttpProtocol.log_request = lambda *a: None # Redirect logging other messages by the underlying WSGI software. wsgi.HttpProtocol.log_message = \ lambda s, f, *a: logger.error('ERROR WSGI: ' + f % a) wsgi.WRITE_TIMEOUT = int(conf.get('client_timeout') or 60) eventlet.hubs.use_hub('poll') eventlet.patcher.monkey_patch(all=False, socket=True) app = loadapp('config:%s' % conf_file, global_conf={'log_name': log_name})
def run_wsgi(conf_path, app_section, *args, **kwargs): """ Runs the server using the specified number of workers. :param conf_path: Path to paste.deploy style configuration file/directory :param app_section: App name from conf file to load config from :returns: 0 if successful, nonzero otherwise """ # Load configuration, Set logger and Load request processor try: (conf, logger, log_name) = \ _initrp(conf_path, app_section, *args, **kwargs) except ConfigFileError as e: print e return 1 # bind to address and port sock = get_socket(conf, default_port=kwargs.get('default_port', 8080)) # remaining tasks should not require elevated privileges drop_privileges(conf.get('user', 'ubuntu')) # Ensure the configuration and application can be loaded before proceeding. global_conf = {'log_name': log_name} if 'global_conf_callback' in kwargs: kwargs['global_conf_callback'](conf, global_conf) loadapp(conf_path, global_conf=global_conf) # set utils.FALLOCATE_RESERVE if desired reserve = int(conf.get('fallocate_reserve', 0)) if reserve > 0: utils.FALLOCATE_RESERVE = reserve # redirect errors to logger and close stdio capture_stdio(logger) worker_count = config_auto_int_value(conf.get('workers'), CPU_COUNT) # Useful for profiling [no forks]. if worker_count == 0: run_server(conf, logger, sock, global_conf=global_conf) return 0 def kill_children(*args): """Kills the entire process group.""" logger.error('SIGTERM received') signal.signal(signal.SIGTERM, signal.SIG_IGN) running[0] = False os.killpg(0, signal.SIGTERM) def hup(*args): """Shuts down the server, but allows running requests to complete""" logger.error('SIGHUP received') signal.signal(signal.SIGHUP, signal.SIG_IGN) running[0] = False running = [True] signal.signal(signal.SIGTERM, kill_children) signal.signal(signal.SIGHUP, hup) children = [] while running[0]: while len(children) < worker_count: pid = os.fork() if pid == 0: signal.signal(signal.SIGHUP, signal.SIG_DFL) signal.signal(signal.SIGTERM, signal.SIG_DFL) #with open("/home/ubuntu/transition_statistics.txt", "a") as tran_file: # tran_file.write("ESTOU NO FORK!!!\n") oracle_plus.get_oracle_plus().set_attributes(len(children)) oracle.get_oracle().set_attributes(int(conf.get('number_of_replicas', 3)), float(conf.get('average_window_size', 10)), config_true_value(conf.get('use_adaptation', True)), int(conf.get('initial_write_quorum_size', 2)), int(conf.get('initial_read_quorum_size', 2)), conf.get('oracle_log_file', '/home/ubuntu/oracle.txt'), conf.get('oracle_lib_path', '/home/ubuntu/oracle_files/oracle_twitter'), conf.get('oracle_model_path', '/home/ubuntu/oracle_files/oracle_twitter'), conf.get('ip', ''), int(conf.get('port', '')), conf.get('master_ip', ''), conf.get('slave_ips', ''), int(conf.get('replica_reconciliation_timeout', 2)), len(children), worker_count) run_server(conf, logger, sock) logger.notice('Child %d exiting normally' % os.getpid()) return 0 else: logger.notice('Started child %s' % pid) children.append(pid) try: pid, status = os.wait() if os.WIFEXITED(status) or os.WIFSIGNALED(status): logger.error('Removing dead child %s' % pid) children.remove(pid) except OSError as err: if err.errno not in (errno.EINTR, errno.ECHILD): raise except KeyboardInterrupt: logger.notice('User quit') break greenio.shutdown_safe(sock) sock.close() logger.notice('Exited') return 0
except Exception, e: print "Error trying to load config %s: %s" % (conf_file, e) return validate_configuration() # pre-configure logger log_name = conf.get("log_name", app_section) if "logger" in kwargs: logger = kwargs.pop("logger") else: logger = get_logger(conf, log_name, log_to_console=kwargs.pop("verbose", False), log_route="wsgi") # bind to address and port sock = get_socket(conf, default_port=kwargs.get("default_port", 8080)) # remaining tasks should not require elevated privileges drop_privileges(conf.get("user", "swift")) # Ensure the application can be loaded before proceeding. loadapp("config:%s" % conf_file, global_conf={"log_name": log_name}) # redirect errors to logger and close stdio capture_stdio(logger) def run_server(): wsgi.HttpProtocol.default_request_version = "HTTP/1.0" # Turn off logging requests by the underlying WSGI software. wsgi.HttpProtocol.log_request = lambda *a: None # Redirect logging other messages by the underlying WSGI software. wsgi.HttpProtocol.log_message = lambda s, f, *a: logger.error("ERROR WSGI: " + f % a) wsgi.WRITE_TIMEOUT = int(conf.get("client_timeout") or 60) eventlet.hubs.use_hub("poll")
return token def daemonize(pidfile, user=None): try: pid = os.fork() if pid > 0: # exit first parent sys.exit(0) except OSError, e: sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) # decouple from parent environment if user: drop_privileges(user) # do second fork try: pid = os.fork() if pid > 0: # exit from second parent sys.exit(0) except OSError, e: sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) sys.exit(1) pid = str(os.getpid()) file(pidfile, 'w+').write("%s\n" % pid) return pid
def run_wsgi(conf_path, app_section, *args, **kwargs): """ Runs the server using the specified number of workers. :param conf_path: Path to paste.deploy style configuration file/directory :param app_section: App name from conf file to load config from :returns: 0 if successful, nonzero otherwise """ # Load configuration, Set logger and Load request processor try: (conf, logger, log_name) = _initrp(conf_path, app_section, *args, **kwargs) except ConfigFileError as e: print e return 1 # bind to address and port sock = get_socket(conf, default_port=kwargs.get("default_port", 8080)) # remaining tasks should not require elevated privileges drop_privileges(conf.get("user", "swift")) # Ensure the configuration and application can be loaded before proceeding. global_conf = {"log_name": log_name} if "global_conf_callback" in kwargs: kwargs["global_conf_callback"](conf, global_conf) loadapp(conf_path, global_conf=global_conf) # set utils.FALLOCATE_RESERVE if desired reserve = int(conf.get("fallocate_reserve", 0)) if reserve > 0: utils.FALLOCATE_RESERVE = reserve # redirect errors to logger and close stdio capture_stdio(logger) worker_count = config_auto_int_value(conf.get("workers"), CPU_COUNT) # Useful for profiling [no forks]. if worker_count == 0: run_server(conf, logger, sock, global_conf=global_conf) return 0 def kill_children(*args): """Kills the entire process group.""" logger.error("SIGTERM received") signal.signal(signal.SIGTERM, signal.SIG_IGN) running[0] = False os.killpg(0, signal.SIGTERM) def hup(*args): """Shuts down the server, but allows running requests to complete""" logger.error("SIGHUP received") signal.signal(signal.SIGHUP, signal.SIG_IGN) running[0] = False running = [True] signal.signal(signal.SIGTERM, kill_children) signal.signal(signal.SIGHUP, hup) children = [] while running[0]: while len(children) < worker_count: pid = os.fork() if pid == 0: signal.signal(signal.SIGHUP, signal.SIG_DFL) signal.signal(signal.SIGTERM, signal.SIG_DFL) run_server(conf, logger, sock) logger.notice("Child %d exiting normally" % os.getpid()) return 0 else: logger.notice("Started child %s" % pid) children.append(pid) try: pid, status = os.wait() if os.WIFEXITED(status) or os.WIFSIGNALED(status): logger.error("Removing dead child %s" % pid) children.remove(pid) except OSError as err: if err.errno not in (errno.EINTR, errno.ECHILD): raise except KeyboardInterrupt: logger.notice("User quit") break greenio.shutdown_safe(sock) sock.close() logger.notice("Exited") return 0
def run_wsgi(conf_path, app_section, *args, **kwargs): """ Runs the server using the specified number of workers. :param conf_path: Path to paste.deploy style configuration file/directory :param app_section: App name from conf file to load config from :returns: 0 if successful, nonzero otherwise """ # Load configuration, Set logger and Load request processor try: (conf, logger, log_name) = \ _initrp(conf_path, app_section, *args, **kwargs) except ConfigFileError as e: print(e) return 1 print('conf,logger,log_name',conf,logger,log_name) # bind to address and port try: sock = get_socket(conf) except ConfigFilePortError: msg = 'bind_port wasn\'t properly set in the config file. ' \ 'It must be explicitly set to a valid port number.' logger.error(msg) print(msg) return 1 print('sock',sock) # remaining tasks should not require elevated privileges drop_privileges(conf.get('user', 'swift')) # Ensure the configuration and application can be loaded before proceeding. global_conf = {'log_name': log_name} if 'global_conf_callback' in kwargs: kwargs['global_conf_callback'](conf, global_conf) print('**** calling loadapp function start *****') #loadapp(conf_path, global_conf=global_conf) print('**** calling loadapp function end *****') # set utils.FALLOCATE_RESERVE if desired reserve = int(conf.get('fallocate_reserve', 0)) print('reserve',reserve) if reserve > 0: utils.FALLOCATE_RESERVE = reserve # redirect errors to logger and close stdio capture_stdio(logger) print('capture_studio done') worker_count = config_auto_int_value(conf.get('workers'), CPU_COUNT) print('worker_count',worker_count) # Useful for profiling [no forks]. if worker_count == 0: run_server(conf, logger, sock, global_conf=global_conf) print('run_server when worker_count is 0') return 0 def kill_children(*args): """Kills the entire process group.""" logger.error('SIGTERM received') signal.signal(signal.SIGTERM, signal.SIG_IGN) running[0] = False os.killpg(0, signal.SIGTERM) def hup(*args): """Shuts down the server, but allows running requests to complete""" logger.error('SIGHUP received') signal.signal(signal.SIGHUP, signal.SIG_IGN) running[0] = False running = [True] signal.signal(signal.SIGTERM, kill_children) signal.signal(signal.SIGHUP, hup) children = [] while running[0]: while len(children) < worker_count: pid = os.fork() print('pid',pid) if pid == 0: signal.signal(signal.SIGHUP, signal.SIG_DFL) signal.signal(signal.SIGTERM, signal.SIG_DFL) print('') print('in run_wsgi now calling run_server,conf,logger,sock',conf,logger,sock) print('') run_server(conf, logger, sock) logger.notice('Child %d exiting normally' % os.getpid()) return 0 else: logger.notice('Started child %s' % pid) children.append(pid) try: pid, status = os.wait() if os.WIFEXITED(status) or os.WIFSIGNALED(status): logger.error('Removing dead child %s' % pid) children.remove(pid) except OSError as err: if err.errno not in (errno.EINTR, errno.ECHILD): raise except KeyboardInterrupt: logger.notice('User quit') break greenio.shutdown_safe(sock) sock.close() logger.notice('Exited') return 0