def __init__(self, config, service_id, worker_id, parent_pipe, started_hooks, graceful_shutdown_timeout): super(ServiceWorker, self).__init__() self._ready = threading.Event() if parent_pipe is not None: _utils.spawn(self._watch_parent_process, parent_pipe) # Reseed random number generator random.seed() args = tuple() if config.args is None else config.args kwargs = dict() if config.kwargs is None else config.kwargs self.service = config.service(worker_id, *args, **kwargs) self.service._initialize(worker_id) if self.service.graceful_shutdown_timeout is None: self.service.graceful_shutdown_timeout = graceful_shutdown_timeout self.title = "%(name)s(%(worker_id)d) [%(pid)d]" % dict( name=self.service.name, worker_id=worker_id, pid=os.getpid()) # Set process title _utils.setproctitle("%(pname)s: %(name)s worker(%(worker_id)d)" % dict(pname=_utils.get_process_name(), name=self.service.name, worker_id=worker_id)) # We are ready tell them self._ready.set() _utils.run_hooks('new_worker', started_hooks, service_id, worker_id, self.service)
def __init__(self, config, service_id, worker_id, parent_pipe, started_hooks, graceful_shutdown_timeout): super(ServiceWorker, self).__init__() self._ready = threading.Event() _utils.spawn(self._watch_parent_process, parent_pipe) # Reseed random number generator random.seed() args = tuple() if config.args is None else config.args kwargs = dict() if config.kwargs is None else config.kwargs self.service = config.service(worker_id, *args, **kwargs) self.service._initialize(worker_id) if self.service.graceful_shutdown_timeout is None: self.service.graceful_shutdown_timeout = graceful_shutdown_timeout self.title = "%(name)s(%(worker_id)d) [%(pid)d]" % dict( name=self.service.name, worker_id=worker_id, pid=os.getpid()) # Set process title _utils.setproctitle( "%(pname)s: %(name)s worker(%(worker_id)d)" % dict( pname=_utils.get_process_name(), name=self.service.name, worker_id=worker_id)) # We are ready tell them self._ready.set() _utils.run_hooks('new_worker', started_hooks, service_id, worker_id, self.service)
def _start_worker(self, service_id, worker_id): self._slowdown_respawn_if_needed() pid = os.fork() if pid != 0: self._running_services[service_id][pid] = worker_id return # reset parent signals signal.signal(signal.SIGINT, signal.SIG_DFL) signal.signal(signal.SIGALRM, signal.SIG_DFL) signal.signal(signal.SIGTERM, signal.SIG_DFL) signal.signal(signal.SIGHUP, signal.SIG_DFL) # Close write to ensure only parent has it open os.close(self.writepipe) os.close(self.signal_pipe_r) os.close(self.signal_pipe_w) _utils.spawn(self._watch_parent_process) # Reseed random number generator random.seed() # Create and run a new service with _utils.exit_on_exception(): self._current_process = _service.ServiceWorker( self._services[service_id], worker_id, self._graceful_shutdown_timeout) self._run_hooks('new_worker', service_id, worker_id, self._current_process.service) self._current_process.wait_forever()
def window_sanity_check(): p = cotyledon.ServiceManager() p.add(LigthService) t = _utils.spawn(p.run) time.sleep(10) os.kill(os.getpid(), signal.SIGTERM) t.join()
def run(self, wait_interval=0.01, graceful_shutdown_timeout=60): """Start and supervise services workers This method will start and supervise all children processes until the master process asked to shutdown by a SIGTERM. All spawned processes are part of the same unix process group. """ self._running_services = collections.defaultdict(dict) self._forktimes = [] self._graceful_shutdown_timeout = graceful_shutdown_timeout self._wait_interval = wait_interval self._dead = threading.Event() # NOTE(sileht): Set it on startup, so first iteration # will spawn initial workers self._got_sig_chld = threading.Event() self._got_sig_chld.set() self._child_supervisor = None self._hooks = { 'terminate': [], 'reload': [], 'new_worker': [], } self._death_detection_pipe = multiprocessing.Pipe(duplex=False) self._systemd_notify_once() self._child_supervisor = _utils.spawn(self._child_supervisor_thread) self._wait_forever()
def _on_signal_received(self, sig): # Code below must not block to return to select.select() and catch # next signals if sig == _utils.SIGALRM: self._alarm() elif sig == signal.SIGTERM: LOG.info('Caught SIGTERM signal, ' 'graceful exiting of service %s' % self.title) if self.service.graceful_shutdown_timeout > 0: if os.name == "posix": signal.alarm(self.service.graceful_shutdown_timeout) else: threading.Timer(self.service.graceful_shutdown_timeout, self._alarm).start() _utils.spawn(self.service._terminate) elif sig == _utils.SIGHUP: _utils.spawn(self.service._reload)
def _on_signal_received(self, sig): # Code below must not block to return to select.select() and catch # next signals if sig == signal.SIGALRM: LOG.info('Graceful shutdown timeout (%d) exceeded, ' 'exiting %s now.' % (self.service.graceful_shutdown_timeout, self.title)) os._exit(1) elif sig == signal.SIGTERM: LOG.info('Caught SIGTERM signal, ' 'graceful exiting of service %s' % self.title) if self.service.graceful_shutdown_timeout > 0: signal.alarm(self.service.graceful_shutdown_timeout) _utils.spawn(self.service._terminate) elif sig == signal.SIGHUP: _utils.spawn(self.service._reload)
def run(self): """Start and supervise services workers This method will start and supervise all children processes until the master process asked to shutdown by a SIGTERM. All spawned processes are part of the same unix process group. """ self._systemd_notify_once() self._child_supervisor = _utils.spawn(self._child_supervisor_thread) self._wait_forever()
def wait_forever(self): LOG.debug("Run service %s" % self.title) _utils.spawn(self.service._run) super(ServiceWorker, self)._wait_forever()