def main(): shell.check_python() # fix py2exe if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) config = shell.get_config(True) daemon.daemon_exec(config) logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) daemon.set_user(config.get('user', None)) loop.run()
def main(): utils.check_python() # fix py2exe if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) config = utils.get_config(True) utils.print_shadowsocks() encrypt.init_table(config['password'], config['method']) try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) tcp_server = tcprelay.TCPRelay(config, True) udp_server = udprelay.UDPRelay(config, True) loop = eventloop.EventLoop() tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) loop.run() except (KeyboardInterrupt, IOError, OSError) as e: logging.error(e) os._exit(0)
def cb_new_server(self, port, password): ret = True port = int(port) if 'server' in self.config: if port in self.tcp_servers_pool: logging.info("server already at %s:%d" % (self.config['server'], port)) return 'this port server is already running' else: a_config = self.config.copy() a_config['server_port'] = port a_config['password'] = password try: logging.info("starting server at %s:%d" % (a_config['server'], port)) tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) tcp_server.add_to_loop(self.loop) self.tcp_servers_pool[port] = tcp_server #udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) #udp_server.add_to_loop(self.loop) #self.udp_servers_pool.update({port: udp_server}) except Exception, e: logging.warn(e)
def main(): shell.check_python() # fix py2exe if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) config = shell.get_config(True) if not config.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False daemon.daemon_exec(config) logging.info( "local start with protocol[%s] password [%s] method [%s] obfs [%s] obfs_param [%s]" % (config['protocol'], config['password'], config['method'], config['obfs'], config['obfs_param'])) try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1)
def add_port(self, config): port = int(config['server_port']) servers = self._relays.get(port, None) if servers: logging.error("server already exists at %s:%d" % (config['server'], port)) return logging.info("adding server at %s:%d" % (config['server'], port)) t = tcprelay.TCPRelay(config, self._dns_resolver, False, self.stat_callback) u = udprelay.UDPRelay(config, self._dns_resolver, False, self.stat_callback) t.add_to_loop(self._loop) u.add_to_loop(self._loop) self._relays[port] = (t, u)
def main(): loop = eventloop.EventLoop() dns_resolver = asyncdns.DNSResolver(loop) tcp_server = tcprelay.TCPRelay(dns_resolver, loop) udp_server = udprelay.UDPRelay(dns_resolver, loop) def handler(signum, _): logging.warning('received SIGQUIT, doing graceful shutting down..') tcp_server.close() udp_server.close() signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) loop.run()
def main(): utils.check_python() # fix py2exe if hasattr(sys, "frozen") and sys.frozen in \ ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) config = utils.get_config(True) utils.print_shadowsocks() encrypt.init_table(config['password'], config['method']) try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver() tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) loop.run() except (KeyboardInterrupt, IOError, OSError) as e: logging.error(e) if config['verbose']: import traceback traceback.print_exc() os._exit(1)
def main(): import logging # -- import from shadowsockesr-v import conf import exit import shell import eventloop import tcprelay import udprelay import asyncdns # -- init logging -- conf.logger_init() # show version logging.info(conf.version()) # -- starting ssr -- # get ssr configurations ssr_conf = shell.get_ssr_conf(ssr_conf_path=conf.ssr_conf_path()) if not ssr_conf.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False password = ssr_conf['password'] method = ssr_conf['method'] protocol = ssr_conf['protocol'] protocol_param = ssr_conf['protocol_param'] obfs = ssr_conf['obfs'] obfs_param = ssr_conf['obfs_param'] udp_enable = ssr_conf['udp_enable'] dns_list = ssr_conf['dns'] logging.info(f'Server start with ' f'password [{password}] ' f'method [{method}] ' f'protocol[{protocol}] ' f'protocol_param[{protocol_param}] ' f'obfs [{obfs}] ' f'obfs_param [{obfs_param}]') server = ssr_conf['server'] port = ssr_conf['server_port'] logging.info(f'Starting server at [{server}]:{port}') try: ssr_conf['out_bind'] = '' ssr_conf['out_bindv6'] = '' # create epoll (singleton) loop = eventloop.EventLoop() # dns server (singleton) dns_resolver = asyncdns.DNSResolver(dns_list) dns_resolver.add_to_loop(loop) stat_counter_dict = {} # listen tcp && register socket tcp = tcprelay.TCPRelay(ssr_conf, dns_resolver, stat_counter=stat_counter_dict) tcp.add_to_loop(loop) if udp_enable: # listen udp && register socket udp = udprelay.UDPRelay(ssr_conf, dns_resolver, False, stat_counter=stat_counter_dict) udp.add_to_loop(loop) # run epoll to handle socket loop.run() except Exception as e: exit.error(e)
def main(): utils.check_python() config = utils.get_config(False) utils.print_shadowsocks() if config['port_password']: if config['server_port'] or config['password']: logging.warn('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: config['port_password'] = {} config['port_password'][str( config['server_port'])] = config['password'] encrypt.init_table(config['password'], config['method']) tcp_servers = [] udp_servers = [] for port, password in config['port_password'].items(): a_config = config.copy() a_config['server_port'] = int(port) a_config['password'] = password logging.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, False)) udp_servers.append(udprelay.UDPRelay(a_config, False)) def run_server(): try: loop = eventloop.EventLoop() for tcp_server in tcp_servers: tcp_server.add_to_loop(loop) for udp_server in udp_servers: udp_server.add_to_loop(loop) loop.run() except (KeyboardInterrupt, IOError, OSError) as e: logging.error(e) import traceback traceback.print_exc() os._exit(0) if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in xrange(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: os.kill(pid, signum) os.waitpid(pid, 0) sys.exit() import signal signal.signal(signal.SIGTERM, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()
def main(): shell.check_python() # fix py2exe if hasattr(sys, "frozen") and sys.frozen in ("windows_exe", "console_exe"): p = os.path.dirname(os.path.abspath(sys.executable)) os.chdir(p) config = shell.get_config(True) #added by cloud for local random choose a server and the port and the port_password if config['port_password']: if config['password']: logging.warn( 'warning: port_password should not be used with server_port and password. server_port and password will be ignored' ) # config['server_port'] = int(random.choice(config['port_password'].items())[0]) if config.has_key('server_port'): if type(config['server_port']) == list and config['server_port']: config['server_port'] = random.choice( config.get('server_port', 8388)) elif config['server_port']: config['server_port'] == int( common.to_str(config.get('server_port', 8388))) else: config['server_port'] = int( random.choice(config['port_password'].items())[0]) else: config['server_port'] = int( random.choice(config['port_password'].items())[0]) if not config['password'] or str(config['password']) == "": config['password'] = common.to_str( config['port_password']["%s" % config['server_port']]) else: if type(config['server_port']) == list and config['server_port']: config['server_port'] = random.choice( config.get('server_port', 8388)) else: config['server_port'] == int( common.to_str(config.get('server_port', 8388))) config["password"] = str( config["port_password"]["%s" % config["server_port"]]).strip() logging.warn('!' * 30) logging.info( "OK.. I choose this guy to help me f**k the GFW.. [ %s : %s : %s : %s : %s]" % (config['server'], config['server_port'], config['password'], config['server_info']["%s" % config['server']], config['method'])) logging.warn('!' * 30) time.sleep(1) daemon.daemon_exec(config) try: logging.info("starting local at %s:%d" % (config['local_address'], config['local_port'])) dns_resolver = asyncdns.DNSResolver(config) tcp_server = tcprelay.TCPRelay(config, dns_resolver, True) udp_server = udprelay.UDPRelay(config, dns_resolver, True) loop = eventloop.EventLoop(config) dns_resolver.add_to_loop(loop) tcp_server.add_to_loop(loop) udp_server.add_to_loop(loop) def handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') tcp_server.close(next_tick=True) udp_server.close(next_tick=True) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1)
def main(): utils.check_python() config = utils.get_config(False) utils.print_shadowsocks() if config['port_password']: if config['password']: logging.warn('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: config['port_password'] = {} server_port = config['server_port'] if type(server_port) == list: for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: config['port_password'][str(server_port)] = config['password'] encrypt.init_table(config['password'], config['method']) tcp_servers = [] udp_servers = [] dns_resolver = asyncdns.DNSResolver() for port, password in config['port_password'].items(): a_config = config.copy() a_config['server_port'] = int(port) a_config['password'] = password logging.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) def run_server(): def child_handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) try: loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers) loop.run() except (KeyboardInterrupt, IOError, OSError) as e: logging.error(e) if config['verbose']: import traceback traceback.print_exc() os._exit(1) if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in xrange(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()
def main(): import sys import os import signal import resource # -- import from shadowsockesr-v import logger import conf import exit import shell, daemon, eventloop, tcprelay, udprelay, asyncdns, common # get ssr configurations ssr_conf = shell.get_ssr_conf(is_local=False, ssr_conf_path=conf.configuration_path()) # start daemon daemon.daemon_exec(ssr_conf) logger.info('current process open files[cmd\'ulimit -n\'] resource: soft %d hard %d' % resource.getrlimit(resource.RLIMIT_NOFILE)) # todo Multiport -> Single port if not ssr_conf['port_password']: ssr_conf['port_password'] = {} server_port = ssr_conf['server_port'] if type(server_port) == list: for a_server_port in server_port: ssr_conf['port_password'][a_server_port] = ssr_conf['password'] else: ssr_conf['port_password'][str(server_port)] = ssr_conf['password'] if not ssr_conf.get('dns_ipv6', False): asyncdns.IPV6_CONNECTION_SUPPORT = False # no used # if config.get('manager_address', 0): # logging.info('entering manager mode') # manager.run(config) # return tcp_servers = [] udp_servers = [] dns_resolver = asyncdns.DNSResolver() if int(ssr_conf['workers']) > 1: stat_counter_dict = None else: stat_counter_dict = {} port_password = ssr_conf['port_password'] config_password = ssr_conf.get('password', 'm') del ssr_conf['port_password'] for port, password_obfs in port_password.items(): method = ssr_conf["method"] protocol = ssr_conf.get("protocol", 'origin') protocol_param = ssr_conf.get("protocol_param", '') obfs = ssr_conf.get("obfs", 'plain') obfs_param = ssr_conf.get("obfs_param", '') bind = ssr_conf.get("out_bind", '') bindv6 = ssr_conf.get("out_bindv6", '') if type(password_obfs) == list: password = password_obfs[0] obfs = common.to_str(password_obfs[1]) if len(password_obfs) > 2: protocol = common.to_str(password_obfs[2]) elif type(password_obfs) == dict: password = password_obfs.get('password', config_password) method = common.to_str(password_obfs.get('method', method)) protocol = common.to_str(password_obfs.get('protocol', protocol)) protocol_param = common.to_str(password_obfs.get('protocol_param', protocol_param)) obfs = common.to_str(password_obfs.get('obfs', obfs)) obfs_param = common.to_str(password_obfs.get('obfs_param', obfs_param)) bind = password_obfs.get('out_bind', bind) bindv6 = password_obfs.get('out_bindv6', bindv6) else: password = password_obfs a_config = ssr_conf.copy() ipv6_ok = False logger.info("server start with protocol[%s] password [%s] method [%s] obfs [%s] obfs_param [%s]" % (protocol, password, method, obfs, obfs_param)) if 'server_ipv6' in a_config: try: if len(a_config['server_ipv6']) > 2 and a_config['server_ipv6'][0] == "[" and a_config['server_ipv6'][-1] == "]": a_config['server_ipv6'] = a_config['server_ipv6'][1:-1] a_config['server_port'] = int(port) a_config['password'] = password a_config['method'] = method a_config['protocol'] = protocol a_config['protocol_param'] = protocol_param a_config['obfs'] = obfs a_config['obfs_param'] = obfs_param a_config['out_bind'] = bind a_config['out_bindv6'] = bindv6 a_config['server'] = a_config['server_ipv6'] logger.info("starting server at [%s]:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) if a_config['server_ipv6'] == '::': ipv6_ok = True except Exception as e: logger.error(e) try: a_config = ssr_conf.copy() a_config['server_port'] = int(port) a_config['password'] = password a_config['method'] = method a_config['protocol'] = protocol a_config['protocol_param'] = protocol_param a_config['obfs'] = obfs a_config['obfs_param'] = obfs_param a_config['out_bind'] = bind a_config['out_bindv6'] = bindv6 logger.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False, stat_counter=stat_counter_dict)) except Exception as e: if not ipv6_ok: logger.error(e) def run_server(): def child_handler(signum, _): logger.warning('received SIGQUIT, doing graceful shutting down..') list(map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) daemon.set_user(ssr_conf.get('user', None)) loop.run() except Exception as e: exit.error(e) if int(ssr_conf['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(ssr_conf['workers'])): r = os.fork() if r == 0: logger.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) os.waitpid(pid, 0) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGINT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logger.warning('worker is only available on Unix/Linux') run_server() else: run_server()
class ServerPool(object): instance = None def __init__(self): utils.check_python() self.config = utils.get_config(False) utils.print_shadowsocks() self.dns_resolver = asyncdns.DNSResolver() self.mgr = asyncmgr.ServerMgr() self.tcp_servers_pool = {} self.tcp_ipv6_servers_pool = {} self.udp_servers_pool = {} self.udp_ipv6_servers_pool = {} self.loop = eventloop.EventLoop() thread.start_new_thread(ServerPool._loop, (self.loop, self.dns_resolver, self.mgr)) @staticmethod def get_instance(): if ServerPool.instance is None: ServerPool.instance = ServerPool() return ServerPool.instance @staticmethod def _loop(loop, dns_resolver, mgr): try: mgr.add_to_loop(loop) dns_resolver.add_to_loop(loop) loop.run() except (KeyboardInterrupt, IOError, OSError) as e: logging.error(e) import traceback traceback.print_exc() os.exit(0) def server_is_run(self, port): port = int(port) ret = 0 if port in self.tcp_servers_pool: ret = 1 if port in self.tcp_ipv6_servers_pool: ret |= 2 return ret def server_run_status(self, port): if 'server' in self.config: if port not in self.tcp_servers_pool: return False if 'server_ipv6' in self.config: if port not in self.tcp_ipv6_servers_pool: return False return True def new_server(self, port, password): ret = True port = int(port) if 'server' in self.config: if port in self.tcp_servers_pool: logging.info("server already at %s:%d" % (self.config['server'], port)) return 'this port server is already running' else: a_config = self.config.copy() a_config['server_port'] = port a_config['password'] = password try: logging.info("starting server at %s:%d" % (a_config['server'], port)) tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) tcp_server.add_to_loop(self.loop) self.tcp_servers_pool.update({port: tcp_server}) udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) udp_server.add_to_loop(self.loop) self.udp_servers_pool.update({port: udp_server}) except Exception, e: logging.warn(e) if 'server_ipv6' in self.config: if port in self.tcp_ipv6_servers_pool: logging.info("server already at %s:%d" % (self.config['server_ipv6'], port)) return 'this port server is already running' else: a_config = self.config.copy() a_config['server'] = a_config['server_ipv6'] a_config['server_port'] = port a_config['password'] = password try: logging.info("starting server at %s:%d" % (a_config['server'], port)) tcp_server = tcprelay.TCPRelay(a_config, self.dns_resolver, False) tcp_server.add_to_loop(self.loop) self.tcp_ipv6_servers_pool.update({port: tcp_server}) udp_server = udprelay.UDPRelay(a_config, self.dns_resolver, False) udp_server.add_to_loop(self.loop) self.udp_ipv6_servers_pool.update({port: udp_server}) except Exception, e: logging.warn(e)
def main(): shell.check_python() config = shell.get_config(False) daemon.daemon_exec(config) if config['port_password']: if config['password']: logging.warn('warning: port_password should not be used with ' 'server_port and password. server_port and password ' 'will be ignored') else: config['port_password'] = {} server_port = config['server_port'] if type(server_port) == list: for a_server_port in server_port: config['port_password'][a_server_port] = config['password'] else: config['port_password'][str(server_port)] = config['password'] if config.get('manager_address', 0): logging.info('entering manager mode') manager.run(config) return tcp_servers = [] udp_servers = [] if 'dns_server' in config: # allow override settings in resolv.conf dns_resolver = asyncdns.DNSResolver(config['dns_server'], config['prefer_ipv6']) else: dns_resolver = asyncdns.DNSResolver(prefer_ipv6=config['prefer_ipv6']) port_password = config['port_password'] del config['port_password'] for port, password in port_password.items(): a_config = config.copy() a_config['server_port'] = int(port) a_config['password'] = password logging.info("starting server at %s:%d" % (a_config['server'], int(port))) tcp_servers.append(tcprelay.TCPRelay(a_config, dns_resolver, False)) udp_servers.append(udprelay.UDPRelay(a_config, dns_resolver, False)) def run_server(): def child_handler(signum, _): logging.warn('received SIGQUIT, doing graceful shutting down..') list( map(lambda s: s.close(next_tick=True), tcp_servers + udp_servers)) signal.signal(getattr(signal, 'SIGQUIT', signal.SIGTERM), child_handler) def int_handler(signum, _): sys.exit(1) signal.signal(signal.SIGINT, int_handler) try: loop = eventloop.EventLoop() dns_resolver.add_to_loop(loop) list(map(lambda s: s.add_to_loop(loop), tcp_servers + udp_servers)) daemon.set_user(config.get('user', None)) loop.run() except Exception as e: shell.print_exception(e) sys.exit(1) if int(config['workers']) > 1: if os.name == 'posix': children = [] is_child = False for i in range(0, int(config['workers'])): r = os.fork() if r == 0: logging.info('worker started') is_child = True run_server() break else: children.append(r) if not is_child: def handler(signum, _): for pid in children: try: os.kill(pid, signum) os.waitpid(pid, 0) except OSError: # child may already exited pass sys.exit() signal.signal(signal.SIGTERM, handler) signal.signal(signal.SIGQUIT, handler) signal.signal(signal.SIGINT, handler) # master for a_tcp_server in tcp_servers: a_tcp_server.close() for a_udp_server in udp_servers: a_udp_server.close() dns_resolver.close() for child in children: os.waitpid(child, 0) else: logging.warn('worker is only available on Unix/Linux') run_server() else: run_server()