def stopall(self, timeout=10): """ Stops all known child processes by calling """ if not self.processes: # No processes running. return all = InProgressAll(process.stop() for process in self.processes.keys()) # Normally we yield InProgressAll objects and they get implicitly connected # by the coroutine code. We're not doing that here, so we connect a dummy # handler so the underlying IPs (the processes) get connected to the IPAll. all.connect(lambda *args: None) # XXX: I've observed SIGCHLD either not be signaled or be missed # with stopall() (but not so far any other time). So this kludge # tries to reap all processes every 0.1s while we're killing child # processes. poll_timer = Timer( lambda: [process._check_dead() for process in self.processes.keys()]) poll_timer.start(0.1) while not all.finished: main.step() poll_timer.stop() # Handle and log any unhandled exceptions from stop() (i.e. child # failed to die) for process in self.processes: try: inprogress(process).result except SystemError, e: log.error(e.message)
def stop( self, cmd = None ): """ Stop the child. If 'cmd' is given, this stop command will send to the app to stop itself. If this is not working, kill -15 and kill -9 will be used to kill the app. Returns an InProgress which finishes when the process stops. """ if self.stopping: return inprogress(self.signals['completed']) if not is_mainthread(): return MainThreadCallback(self.stop, cmd)() self.stopping = True cmd = cmd or self._stop_cmd if self.is_alive() and not self.__kill_timer: if cmd: log.info('sending exit command to app') if callable(cmd): cmd() else: self.write(cmd) cb = Callback( self.__kill, 15 ) self.__kill_timer = notifier.timer_add( 3000, cb ) else: cb = Callback( self.__kill, 15 ) self.__kill_timer = notifier.timer_add( 0, cb ) return inprogress(self.signals['completed'])
def stopall(self, timeout=10): """ Stops all known child processes by calling """ if not self.processes: # No processes running. return all = InProgressAll(process.stop() for process in self.processes.keys()) # Normally we yield InProgressAll objects and they get implicitly connected # by the coroutine code. We're not doing that here, so we connect a dummy # handler so the underlying IPs (the processes) get connected to the IPAll. all.connect(lambda *args: None) # XXX: I've observed SIGCHLD either not be signaled or be missed # with stopall() (but not so far any other time). So this kludge # tries to reap all processes every 0.1s while we're killing child # processes. poll_timer = Timer(lambda: [process._check_dead() for process in self.processes.keys()]) poll_timer.start(0.1) while not all.finished: main.step() poll_timer.stop() # Handle and log any unhandled exceptions from stop() (i.e. child # failed to die) for process in self.processes: try: inprogress(process).result except SystemError, e: log.error(e.message)
def newfunc(*args, **kwargs): generator = Generator() if callback: ip = callback(generator, func, args, kwargs) else: ip = func(generator=generator, *args, **kwargs) try: ip.connect(generator.finish) ip.exception.connect(generator.throw) except AttributeError: raise ValueError('@kaa.generator decorated function (%s) must return InProgress' % func.func_name) return inprogress(generator)
def _async_read(self, signal): """ Common implementation for read() and readline(). """ if not (self._mode & IO_READ): raise IOError(9, 'Cannot read on a write-only channel') if not self.readable: # channel is not readable. Return an InProgress pre-finished # with None return InProgress().finish(None) ip = inprogress(signal) ip.signals['abort'].connect(self._abort_read_inprogress, signal, ip) return ip
def _async_read(self, signal): """ Common implementation for read() and readline(). """ if not (self._mode & IO_READ): raise IOError(9, 'Cannot read on a write-only channel') if not self.readable: # channel is not readable. Return an InProgress pre-finished # with None return InProgress().finish(None) ip = inprogress(signal) def abort(exc): # XXX: closure around ip and signal holds strong refs; is this bad? signal.disconnect(ip) self._update_read_monitor() ip.signals['abort'].connect(abort) return ip