Example #1
0
    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)
Example #2
0
    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,
        )
Example #3
0
    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,
        )
Example #4
0
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()
Example #5
0
    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()
Example #6
0
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()