Esempio n. 1
0
    def run_child(self):
        def child_hup(*args):
            """Shuts down child processes, existing requests are handled."""
            signal.signal(signal.SIGHUP, signal.SIG_IGN)
            eventlet.wsgi.is_accepting = False
            self.sock.close()

        pid = os.fork()
        if pid == 0:
            signal.signal(signal.SIGHUP, child_hup)
            signal.signal(signal.SIGTERM, signal.SIG_DFL)
            # ignore the interrupt signal to avoid a race whereby
            # a child worker receives the signal before the parent
            # and is respawned unnecessarily as a result
            signal.signal(signal.SIGINT, signal.SIG_IGN)
            # The child has no need to stash the unwrapped
            # socket, and the reference prevents a clean
            # exit on sighup
            self._sock = None
            self.run_server()
            LOG.info(_LI('Child %d exiting normally'), os.getpid())
            # self.pool.waitall() is now called in wsgi's server so
            # it's safe to exit here
            sys.exit(0)
        else:
            LOG.info(_LI('Started child %s'), pid)
            self.children.add(pid)
Esempio n. 2
0
    def run_child(self):
        def child_hup(*args):
            """Shuts down child processes, existing requests are handled."""
            signal.signal(signal.SIGHUP, signal.SIG_IGN)
            eventlet.wsgi.is_accepting = False
            self.sock.close()

        pid = os.fork()
        if pid == 0:
            signal.signal(signal.SIGHUP, child_hup)
            signal.signal(signal.SIGTERM, signal.SIG_DFL)
            # ignore the interrupt signal to avoid a race whereby
            # a child worker receives the signal before the parent
            # and is respawned unnecessarily as a result
            signal.signal(signal.SIGINT, signal.SIG_IGN)
            # The child has no need to stash the unwrapped
            # socket, and the reference prevents a clean
            # exit on sighup
            self._sock = None
            self.run_server()
            LOG.info(_LI('Child %d exiting normally'), os.getpid())
            # self.pool.waitall() is now called in wsgi's server so
            # it's safe to exit here
            sys.exit(0)
        else:
            LOG.info(_LI('Started child %s'), pid)
            self.children.add(pid)
Esempio n. 3
0
 def _remove_children(self, pid):
     if pid in self.children:
         self.children.remove(pid)
         LOG.info(_LI('Removed dead child %s'), pid)
     elif pid in self.stale_children:
         self.stale_children.remove(pid)
         LOG.info(_LI('Removed stale child %s'), pid)
     else:
         LOG.warn(_LW('Unrecognised child %s'), pid)
Esempio n. 4
0
 def _remove_children(self, pid):
     if pid in self.children:
         self.children.remove(pid)
         LOG.info(_LI('Removed dead child %s'), pid)
     elif pid in self.stale_children:
         self.stale_children.remove(pid)
         LOG.info(_LI('Removed stale child %s'), pid)
     else:
         LOG.warn(_LW('Unrecognised child %s'), pid)
Esempio n. 5
0
 def _single_run(self, application, sock):
     """Start a WSGI server in a new green thread."""
     LOG.info(_LI("Starting single process server"))
     eventlet.wsgi.server(sock, application,
                          custom_pool=self.pool,
                          url_length_limit=URL_LENGTH_LIMIT,
                          log=self._wsgi_logger,
                          debug=cfg.CONF.debug)
Esempio n. 6
0
 def _single_run(self, application, sock):
     """Start a WSGI server in a new green thread."""
     LOG.info(_LI("Starting single process server"))
     eventlet.wsgi.server(sock,
                          application,
                          custom_pool=self.pool,
                          url_length_limit=URL_LENGTH_LIMIT,
                          log=self._wsgi_logger,
                          debug=cfg.CONF.debug)
Esempio n. 7
0
 def _verify_and_respawn_children(self, pid, status):
     if len(self.stale_children) == 0:
         LOG.debug('No stale children')
     if os.WIFEXITED(status) and os.WEXITSTATUS(status) != 0:
         LOG.error(_LE('Not respawning child %d, cannot '
                       'recover from termination'), pid)
         if not self.children and not self.stale_children:
             LOG.info(
                 _LI('All workers have terminated. Exiting'))
             self.running = False
     else:
         if len(self.children) < self.conf.workers:
             self.run_child()
Esempio n. 8
0
    def start_wsgi(self):
        if self.conf.workers == 0:
            # Useful for profiling, test, debug etc.
            self.pool = eventlet.GreenPool(size=self.threads)
            self.pool.spawn_n(self._single_run, self.application, self.sock)
            return

        LOG.info(_LI("Starting %d workers"), self.conf.workers)
        signal.signal(signal.SIGTERM, self.kill_children)
        signal.signal(signal.SIGINT, self.kill_children)
        signal.signal(signal.SIGHUP, self.hup)
        while len(self.children) < self.conf.workers:
            self.run_child()
Esempio n. 9
0
 def _verify_and_respawn_children(self, pid, status):
     if len(self.stale_children) == 0:
         LOG.debug('No stale children')
     if os.WIFEXITED(status) and os.WEXITSTATUS(status) != 0:
         LOG.error(
             _LE('Not respawning child %d, cannot '
                 'recover from termination'), pid)
         if not self.children and not self.stale_children:
             LOG.info(_LI('All workers have terminated. Exiting'))
             self.running = False
     else:
         if len(self.children) < self.conf.workers:
             self.run_child()
Esempio n. 10
0
    def start_wsgi(self):
        if self.conf.workers == 0:
            # Useful for profiling, test, debug etc.
            self.pool = eventlet.GreenPool(size=self.threads)
            self.pool.spawn_n(self._single_run, self.application, self.sock)
            return

        LOG.info(_LI("Starting %d workers"), self.conf.workers)
        signal.signal(signal.SIGTERM, self.kill_children)
        signal.signal(signal.SIGINT, self.kill_children)
        signal.signal(signal.SIGHUP, self.hup)
        while len(self.children) < self.conf.workers:
            self.run_child()
Esempio n. 11
0
 def wait_on_children(self):
     while self.running:
         try:
             pid, status = os.wait()
             if os.WIFEXITED(status) or os.WIFSIGNALED(status):
                 self._remove_children(pid)
                 self._verify_and_respawn_children(pid, status)
         except OSError as err:
             if err.errno not in (errno.EINTR, errno.ECHILD):
                 raise
         except KeyboardInterrupt:
             LOG.info(_LI('Caught keyboard interrupt. Exiting.'))
             os.killpg(0, signal.SIGTERM)
             break
         except exception.SIGHUPInterrupt:
             self.reload()
             continue
     eventlet.greenio.shutdown_safe(self.sock)
     self.sock.close()
     LOG.debug('Exited')
Esempio n. 12
0
 def wait_on_children(self):
     while self.running:
         try:
             pid, status = os.wait()
             if os.WIFEXITED(status) or os.WIFSIGNALED(status):
                 self._remove_children(pid)
                 self._verify_and_respawn_children(pid, status)
         except OSError as err:
             if err.errno not in (errno.EINTR, errno.ECHILD):
                 raise
         except KeyboardInterrupt:
             LOG.info(_LI('Caught keyboard interrupt. Exiting.'))
             os.killpg(0, signal.SIGTERM)
             break
         except exception.SIGHUPInterrupt:
             self.reload()
             continue
     eventlet.greenio.shutdown_safe(self.sock)
     self.sock.close()
     LOG.debug('Exited')
Esempio n. 13
0
def main():
    try:
        logging.register_options(cfg.CONF)
        cfg.CONF(project='abbot',
                 prog='abbot-api',
                 version=version.version_info.version_string())
        logging.setup(cfg.CONF, 'abbot-api')
        messaging.setup()

        app = config.load_paste_app()

        port = cfg.CONF.abbot_api.bind_port
        host = cfg.CONF.abbot_api.bind_host
        LOG.info(_LI('Starting abbot REST API on %(host)s:%(port)s'), {
            'host': host,
            'port': port
        })
        server = wsgi.Server('abbot-api', cfg.CONF.abbot_api)
        server.start(app, default_port=port)
        systemd.notify_once()
        server.wait()
    except RuntimeError as e:
        msg = six.text_type(e)
        sys.exit("ERROR: %s" % msg)