def __init__(self, sock, basepath, module, name, version, args, ssl_options=None, canary=False, debug=False): self.module = module self.name = name self.version = version self.basepath = basepath self.args = args self.ssl_options = ssl_options self.ppid = os.getppid() self.canary = canary self.children = set() self.debug = debug self.logger = get_logger('zygote.worker.zygote_process', self.debug) establish_signal_handlers(self.logger) # Set up the control socket nice and early try: self.control_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0) self.control_socket.bind('\0zygote_%d' % os.getpid()) except Exception: # If we can't bind to the control socket, just give up self.logger.error("Could not bind to control socket, aborting early!") sys.exit(INIT_FAILURE_EXIT_CODE) try: self._real_init(sock, self.basepath, self.module, args) except Exception: self.logger.exception("Error performing initialization of %s", self) sys.exit(INIT_FAILURE_EXIT_CODE)
def __init__( self, sock, basepath, module, name, version, num_workers, control_port, control_socket_path, application_args=None, max_requests=None, zygote_base=None, ssl_options=None, debug=False ): self.logger = get_logger('zygote.master', debug) if self.__class__.instantiated: self.logger.error('cannot instantiate zygote master more than once') sys.exit(1) self.__class__.instantiated = True self.sock = sock self.basepath = basepath self.module = module self.name = name self.version = version self.num_workers = num_workers self.control_port = control_port self.control_socket_path = control_socket_path self.application_args = application_args or [] self.max_requests = max_requests self.zygote_base = zygote_base self.ssl_options = ssl_options self.debug = debug self.stopped = False self.started_transition = None self.prev_zygote = None self.current_zygote = None self.time_created = datetime.datetime.now() self.io_loop = ZygoteIOLoop(log_name='zygote.master.ioloop') self.zygote_collection = accounting.ZygoteCollection() self.setup_master_socket() self.setup_control_socket() signal.signal(signal.SIGCHLD, self.reap_child) signal.signal(signal.SIGHUP, self.update_revision) for sig in (signal.SIGINT, signal.SIGTERM, signal.SIGQUIT): signal.signal(sig, self.stop) self.open_fds, self.status_http_server = handlers.get_httpserver( self.io_loop, self.control_port, self, zygote_base=self.zygote_base, ssl_options=self.ssl_options, )
def __init__(self, sock, basepath, module, name, version, num_workers, control_port, control_socket_path, application_args=None, max_requests=None, zygote_base=None, ssl_options=None, debug=False): self.logger = get_logger('zygote.master', debug) if self.__class__.instantiated: self.logger.error( 'cannot instantiate zygote master more than once') sys.exit(1) self.__class__.instantiated = True self.sock = sock self.basepath = basepath self.module = module self.name = name self.version = version self.num_workers = num_workers self.control_port = control_port self.control_socket_path = control_socket_path self.application_args = application_args or [] self.max_requests = max_requests self.zygote_base = zygote_base self.ssl_options = ssl_options self.debug = debug self.stopped = False self.started_transition = None self.prev_zygote = None self.current_zygote = None self.time_created = datetime.datetime.now() self.io_loop = ZygoteIOLoop(log_name='zygote.master.ioloop') self.zygote_collection = accounting.ZygoteCollection() self.setup_master_socket() self.setup_control_socket() signal.signal(signal.SIGCHLD, self.reap_child) signal.signal(signal.SIGHUP, self.update_revision) for sig in (signal.SIGINT, signal.SIGTERM, signal.SIGQUIT): signal.signal(sig, self.stop) self.open_fds, self.status_http_server = handlers.get_httpserver( self.io_loop, self.control_port, self, zygote_base=self.zygote_base, ssl_options=self.ssl_options, )
def main(opts, extra_args): setproctitle('zygote master %s' % (opts.name or opts.module, )) zygote_logger = get_logger('zygote', opts.debug) if not logging.root.handlers: # XXX: WARNING # # We're disabling the root logger. Tornado's RequestHandler ONLY # supports logging uncaught errors to the root logger. This will end # poorly for you! # # We should probably provide a RequestHandler subclass that has # _handle_request_exception overridden to do something useful. # That might be hard to do without adding a tight version dependency # on tornado. logging.root.addHandler(NullHandler()) if opts.debug: logging.root.setLevel(logging.DEBUG) else: logging.root.setLevel(logging.INFO) zygote_logger.info('main started') # Create the TCP listen socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) flags = fcntl.fcntl(sock.fileno(), fcntl.F_GETFD) flags |= fcntl.FD_CLOEXEC fcntl.fcntl(sock.fileno(), fcntl.F_SETFD, flags) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setblocking(0) sock.bind((opts.interface, opts.port)) sock.listen(128) ssl_options = None if opts.cert: ssl_options = dict( certfile=opts.cert, keyfile=opts.key, ca_certs=opts.cacerts, cert_reqs=ssl.CERT_OPTIONAL if opts.cacerts else ssl.CERT_NONE, ) zygote_logger.info('using SSL with %s', ssl_options) sock = ssl.wrap_socket(sock, server_side=True, do_handshake_on_connect=False, **ssl_options) master = ZygoteMaster(sock, basepath=opts.basepath, module=opts.module, name=opts.name or opts.module, version=opts.version, num_workers=opts.num_workers, control_port=opts.control_port, control_socket_path=opts.control_socket_path, application_args=extra_args, max_requests=opts.max_requests, zygote_base=opts.zygote_base, ssl_options=ssl_options, debug=opts.debug) atexit.register(master.stop) master.start()
def _initialize_worker(self, time_created): # We're the child. We need to close the write_pipe in order for the # read_pipe to get an event when the parent's write_pipe closes # (otherwise the kernel is too smart and thinks that it's waiting # for writes from *this* process' write_pipe). os.close(self.write_pipe) logger = get_logger('zygote.worker.worker_process') logger.debug('new worker started') def on_parent_exit(fd, events): logger.error('detected that intermediate zygote died, exiting') sys.exit(0) # create a new i/o loop del self.io_loop io_loop = ZygoteIOLoop(log_name='zygote.worker.worker_process.ioloop') # Install this worker's io_loop as the global io_loop; only applies in # this fork. Programs that uses this io_loop instance should NOT use # io_loop.start() because start() is invoked by the corresponding # zygote worker. if tornado.version_info >= (2,1,0): io_loop.install() else: tornado.ioloop.IOLoop._instance = io_loop # add the read pipe io_loop.add_handler(self.read_pipe, on_parent_exit, io_loop.READ) sock = AFUnixSender(io_loop, logger=logger) sock.connect('\0zygote_%d' % self.ppid) establish_signal_handlers(logger) def on_headers(line, remote_ip, headers): logger.debug('sending MessageHTTPBegin') notify(sock, message.MessageHTTPBegin, "%s %s" % (remote_ip, line)) def on_close(disconnected=False): logger.debug('sending MessageHTTPEnd') notify(sock, message.MessageHTTPEnd) notify(sock, message.MessageWorkerStart, '%d %d' % (int(time_created * 1e6), os.getppid())) setproctitle('zygote-worker name=%s version=%s' % (self.name, self._version(),)) try: # io_loop is passed into get_application for program to add handler # or schedule task on the main io_loop. Program that uses this # io_loop instance should NOT use io_loop.start() because start() # is invoked by the corresponding zygote worker. kwargs = {'io_loop': io_loop} logger.debug("Invoking get_application") app = self.get_application(*self.args, **kwargs) except Exception: logger.error("Unable to get application") raise # TODO: make keep-alive servers work logger.debug("Creating HTTPServer") http_server = HTTPServer(app, io_loop=io_loop, no_keep_alive=True, close_callback=on_close, headers_callback=on_headers, ssl_options=self.ssl_options ) if tornado.version_info >= (2,1,0): http_server.add_socket(self.sock) else: http_server._socket = self.sock io_loop.add_handler(self.sock.fileno(), http_server._handle_events, io_loop.READ) logger.debug("Started ioloop...") io_loop.start()
def main(opts, extra_args): setproctitle('zygote master %s' % (opts.module,)) zygote_logger = get_logger('zygote', opts.debug) if not logging.root.handlers: # XXX: WARNING # # We're disabling the root logger. Tornado's RequestHandler ONLY # supports logging uncaught errors to the root logger. This will end # poorly for you! # # We should probably provide a RequestHandler subclass that has # _handle_request_exception overridden to do something useful. # That might be hard to do without adding a tight version dependency # on tornado. logging.root.addHandler(NullHandler()) if opts.debug: logging.root.setLevel(logging.DEBUG) else: logging.root.setLevel(logging.INFO) zygote_logger.info('main started') # Create the TCP listen socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) flags = fcntl.fcntl(sock.fileno(), fcntl.F_GETFD) flags |= fcntl.FD_CLOEXEC fcntl.fcntl(sock.fileno(), fcntl.F_SETFD, flags) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.setblocking(0) sock.bind((opts.interface, opts.port)) sock.listen(128) ssl_options=None if opts.cert: ssl_options = dict( certfile=opts.cert, keyfile=opts.key, ca_certs=opts.cacerts, cert_reqs=ssl.CERT_OPTIONAL if opts.cacerts else ssl.CERT_NONE, ) zygote_logger.info('using SSL with %s', ssl_options) sock = ssl.wrap_socket(sock, server_side=True, do_handshake_on_connect=False, **ssl_options ) master = ZygoteMaster( sock, basepath=opts.basepath, module=opts.module, num_workers=opts.num_workers, control_port=opts.control_port, control_socket_path=opts.control_socket_path, application_args=extra_args, max_requests=opts.max_requests, zygote_base=opts.zygote_base, ssl_options=ssl_options, debug=opts.debug ) atexit.register(master.stop) master.start()