def spawnNewChild(self): """ STEP 1 (parent): New child spawning starts by killing the current child. """ if not self.active: raise CannotSpawnNewChild("Loop not started yet") if self.forking: raise CannotSpawnNewChild("Serious forking action is already going on. Cannot fork now.") if self.child_pid is None: raise CannotSpawnNewChild("No killing yet. Not started child yet") self.pause = False if not self.killed_child or self.isChild(): self._killChild() else: # Ok, we already have sent the SIGINT the child, but asking for new child logger.info("Not sending SIGINT because we already killed the child. Just scheduling new fork.") self._scheduleFork() self.killed_child = True
def spawnNewChild(self): """ STEP 1 (parent): New child spawning starts by killing the current child. """ if not self.active: raise CannotSpawnNewChild("Loop not started yet") if self.forking: raise CannotSpawnNewChild("Serious forking action is already " "going on. Cannot fork now.") if self.child_pid is None: raise CannotSpawnNewChild("No killing yet. Not started child yet") self.pause = False if not self.killed_child or self.isChild(): self._killChild() else: # Ok, we already have sent the SIGINT the child, but asking for new # child logger.info("Not sending SIGINT because we already killed " "the child. Just scheduling new fork.") self._scheduleFork() self.killed_child = True
def _parentExitHandler(self, signum=None, frame=None): if self.isChild(): return self.exit = True if self.isChildAlive(): logger.info("Parent dying. Killing child first.") self._killChild()
def on_any_event(self, event): ext = event.src_path.split(".")[-1].lower() if ext not in self.allowed_extensions: return logger.info("Got '%s' event on %s" % (event.event_type, event.src_path)) try: self.forkloop.spawnNewChild() except CannotSpawnNewChild as e: logger.error(str(e.args[0]))
def start(self): """Start file monitoring thread""" registerHandler(signal.SIGINT, self._exitHandler) registerHandler(signal.SIGTERM, self._exitHandler) for path in self.paths: logger.info("Starting file monitor on %s" % path) observer = Observer() self.observers.append(observer) observer.schedule(self, path=path, recursive=True) observer.start()
def _waitChildToDieAndScheduleNew(self, signal=None, frame=None): """ STEP 3 (parent): Child told us via SIGCHLD that we can spawn new child """ try: # Acknowledge dead child pid, exit_status = os.wait() logger.info("Child %d exited, reasons %s" % (pid, self._resolveExitReason(exit_status))) except OSError: # OSError: [Errno 10] No child processes pass # Schedule new self._scheduleFork()
def start(self): """ Start file monitoring thread """ registerHandler(signal.SIGINT, self._exitHandler) registerHandler(signal.SIGTERM, self._exitHandler) for path in self.paths: logger.info("Starting file monitor on %s" % path) observer = Observer() self.observers.append(observer) observer.schedule(self, path=path, recursive=True) observer.start()
def startForkLoop(event): if not monkeypatcher.PATCHED: errline() errline("sauna.reload is not installed correctly!") errline("Your are missing following line from instance part " "of your buildout:") errline() errline(" zope-conf-additional = %import sauna.reload") errline() errline("Not starting fork loop.") errline() return if not reload_paths: errline() errline("sauna.reload: No paths in RELOAD_PATH environment variable. " "Not starting fork loop.") errline("Set it to your development egg paths to activate reloading") errline() errline("Example:") errline(" $ RELOAD_PATH=src/ bin/instance fg") errline() return # Start fs monitor before the forkloop watcher.Watcher(reload_paths.getParentPaths(), forkloop).start() # Build and execute a configuration file to include meta, configuration and # overrides for dependencies of the deferred development packages. autoinclude.includeDependenciesForDeferred() autoinclude.checkDeferringErrors() config = getConfiguration() zserver = [ server for server in config.servers if isinstance(server, zhttp_server) ][0] logger.info("We saved at least %s seconds from boot up time" % (time.time() - forkloop.boot_started)) logger.info("Overview available at http://127.0.0.1:%i/@@saunareload" % (zserver.port)) forkloop.start()
def on_any_event(self, event): ext = event.src_path.split(".")[-1].lower() if ext not in self.allowed_extensions: return logger.info("Got '%s' event on %s" % (event.event_type, event.src_path)) if ext in ( "html", "xml" ): notify(ThemeChanged()) logger.info("Signaling plone.app.theming") return try: self.forkloop.spawnNewChild() except CannotSpawnNewChild as e: logger.error(str(e.args[0]))
def startForkLoop(event): if not monkeypatcher.PATCHED: errline() errline("sauna.reload is not installed correctly!") errline("Your are missing following line from instance part " "of your buildout:") errline() errline(" zope-conf-additional = %import sauna.reload") errline() errline("Not starting fork loop.") errline() return if not reload_paths: errline() errline("sauna.reload: No paths in RELOAD_PATH environment variable. " "Not starting fork loop.") errline("Set it to your development egg paths to activate reloading") errline() errline("Example:") errline(" $ RELOAD_PATH=src/ bin/instance fg") errline() return # Start fs monitor before the forkloop watcher.Watcher(reload_paths.getParentPaths(), forkloop).start() # Build and execute a configuration file to include meta, configuration and # overrides for dependencies of the deferred development packages. autoinclude.includeDependenciesForDeferred() autoinclude.checkDeferringErrors() config = getConfiguration() zserver = [server for server in config.servers if isinstance(server, zhttp_server)][0] logger.info("We saved at least %s seconds from boot up time" % (time.time() - forkloop.boot_started)) logger.info("Overview available at http://127.0.0.1:%i/@@saunareload" % (zserver.port)) forkloop.start()
def loop(self): """ Magic happens here """ registerHandler(signal.SIGINT, self._parentExitHandler) registerHandler(signal.SIGTERM, self._parentExitHandler) self.active = True logger.info("Fork loop starting on parent. PID %i" % os.getpid()) while True: self.forking = False if self.exit: return if self.fork: self.fork = False if self.pause: # Pause mode. No forks now. continue if not self.killed_child: errline() errline("Child died on bootup. Pausing fork loop for now. ") errline("Fix possible errors and save edits and we'll try booting again.") errline("Waiting...") # Child died because of unknown reason. Mark it as killed # and go into pause mode. self.killed_child = True self.pause = True continue if self.isChildAlive(): # Child is still alive for some reason. Lets wait few # rounds for it to die. continue self.forking = True self.startChildBooTimer() self.child_pid = os.fork() if self.child_pid == 0: break self.killed_child = False time.sleep(1) logger.setChildLogger() logger.info("Forked new child. Installing reloadable products...") self._prepareNewChild() self.forking = False logger.info("Booted up new new child in %s seconds. PID %i" % ( time.time() - self.child_started, os.getpid())) notify(NewChildIsReady(self))
def loop(self): """ Magic happens here """ registerHandler(signal.SIGINT, self._parentExitHandler) registerHandler(signal.SIGTERM, self._parentExitHandler) self.active = True logger.info("Fork loop starting on parent. PID %i" % os.getpid()) while True: self.forking = False if self.exit: return if self.fork: self.fork = False if self.pause: # Pause mode. No forks now. continue if not self.killed_child: errline() errline("Child died on bootup. " "Pausing fork loop for now.") errline("Fix possible errors and save edits " "and we'll try booting again.") errline("Waiting...") # Child died because of unknown reason. Mark it as killed # and go into pause mode. self.killed_child = True self.pause = True continue if self.isChildAlive(): # Child is still alive for some reason. Lets wait few # rounds for it to die. continue self.forking = True self.startChildBooTimer() self.child_pid = os.fork() if self.child_pid == 0: break self.killed_child = False time.sleep(1) logger.setChildLogger() logger.info("Forked new child. Installing reloadable products...") self._prepareNewChild() self.forking = False logger.logDeferredErrors() logger.logDeferred() logger.info("Booted up new child in %s seconds. PID %i" % (time.time() - self.child_started, os.getpid())) notify(NewChildIsReady(self))