def _kill(greenlet, exception, waiter): try: greenlet.throw(exception) except: # XXX do we need this here? greenlet.parent.handle_error(greenlet, *sys.exc_info()) waiter.switch()
def throw(self, *args): """Immediatelly switch into the greenlet and raise an exception in it. Should only be called from the HUB, otherwise the current greenlet is left unscheduled forever. To raise an exception in a safely manner from any greenlet, use :meth:`kill`. If a greenlet was started but never switched to yet, then also a) cancel the event that will start it b) fire the notifications as if an exception was raised in a greenlet """ if self._start_event is None: self._start_event = _dummy_event else: self._start_event.stop() try: greenlet.throw(self, *args) finally: if self._exception is _NONE and self.dead: # the greenlet was never switched to before and it will never be, _report_error was not called # the result was not set and the links weren't notified. let's do it here. # checking that self.dead is true is essential, because throw() does not necessarily kill the greenlet # (if the exception raised by throw() is caught somewhere inside the greenlet). if len(args) == 1: arg = args[0] #if isinstance(arg, type): if type(arg) is type(Exception): args = (arg, arg(), None) else: args = (type(arg), arg, None) elif not args: args = (GreenletExit, GreenletExit(), None) self._report_error(args)
def throw(self, *args): """Immediatelly switch into the greenlet and raise an exception in it. Should only be called from the HUB, otherwise the current greenlet is left unscheduled forever. To raise an exception in a safely manner from any greenlet, use :meth:`kill`. """ if self._start_event is not None: self._start_event.cancel() self._start_event = None if not self.dead: if self: return greenlet.throw(self, *args) else: # special case for when greenlet is not yet started, because _report_error is not executed if len(args)==1: self._exception = args[0] elif not args: self._exception = GreenletExit() else: self._exception = args[1] try: try: # Even though the greenlet is not yet started, we calling throw() here # so that its 'dead' attribute becomes True return greenlet.throw(self, *args) except: # since this function is called from the Hub, which is the parent of *greenlet* # the above statement will re-reraise here whatever we've thrown in it # this traceback is useless, so we silent it pass finally: if self._links and self._notifier is None: self._notifier = core.active_event(self._notify_links)
def __call__(self, source): if source.successful(): if isinstance(source.value, GreenletExit): error = LinkedKilled(source) else: error = LinkedCompleted(source) else: error = LinkedFailed(source) current = getcurrent() greenlet = self.greenlet if current is greenlet: greenlet.throw(error) elif current is get_hub(): try: greenlet.throw(error) except: traceback.print_exc() else: kill(self.greenlet, error)
def throw(self, *args): """Immediatelly switch into the greenlet and raise an exception in it. Should only be called from the HUB, otherwise the current greenlet is left unscheduled forever. To raise an exception in a safe manner from any greenlet, use :meth:`kill`. If a greenlet was started but never switched to yet, then also a) cancel the event that will start it b) fire the notifications as if an exception was raised in a greenlet """ self.__cancel_start() try: if not self.dead: # Prevent switching into a greenlet *at all* if we had never # started it. Usually this is the same thing that happens by throwing, # but if this is done from the hub with nothing else running, prevents a # LoopExit. greenlet.throw(self, *args) finally: self.__handle_death_before_start(*args)
def _kill(greenlet, exception, waiter): greenlet.throw(exception) waiter.switch()
def _kill(greenlet, exception, waiter): try: greenlet.throw(exception) except: traceback.print_exc() waiter.switch()