self.running = False
self.finished = False
self.exc_info = None
+ self.had_exception = False
def register_callback(self, key):
"""Adds ``key`` to the list of callbacks."""
self.exc_info = sys.exc_info()
try:
if self.exc_info is not None:
+ self.had_exception = True
exc_info = self.exc_info
self.exc_info = None
yielded = self.gen.throw(*exc_info)
yielded = self.gen.send(next)
except StopIteration:
self.finished = True
- if self.pending_callbacks:
+ if self.pending_callbacks and not self.had_exception:
+ # If we ran cleanly without waiting on all callbacks
+ # raise an error (really more of a warning). If we
+ # had an exception then some callbacks may have been
+ # orphaned, so skip the check in that case.
raise LeakedCallbackError(
"finished without waiting for callbacks %r" %
self.pending_callbacks)
yielded = Multi(yielded)
if isinstance(yielded, YieldPoint):
self.yield_point = yielded
- self.yield_point.start(self)
+ try:
+ self.yield_point.start(self)
+ except Exception:
+ self.exc_info = sys.exc_info()
else:
self.exc_info = (BadYieldError("yielded unknown object %r" % yielded),)
finally:
1/0
self.assertRaises(ZeroDivisionError, self.run_gen, f)
+ def test_exception_in_task_phase1(self):
+ def fail_task(callback):
+ 1/0
+
+ @gen.engine
+ def f():
+ try:
+ yield gen.Task(fail_task)
+ raise Exception("did not get expected exception")
+ except ZeroDivisionError:
+ self.stop()
+ self.run_gen(f)
+
def test_with_arg(self):
@gen.engine
def f():