diff options
author | brian.quinlan <devnull@localhost> | 2010-07-30 05:50:09 +0000 |
---|---|---|
committer | brian.quinlan <devnull@localhost> | 2010-07-30 05:50:09 +0000 |
commit | ec104f8f187cbcc962b0f720f72f03e3cd981aa5 (patch) | |
tree | 72b87dc1f4305c5abb0d355c4c3f5a160bc0353f | |
parent | 992e94f64f379b6c918469275758309ac753b6ff (diff) | |
download | futures-ec104f8f187cbcc962b0f720f72f03e3cd981aa5.tar.gz |
Handles the case were a Future callback raises.
-rw-r--r-- | docs/index.rst | 11 | ||||
-rw-r--r-- | python3/futures/_base.py | 5 | ||||
-rw-r--r-- | python3/test_futures.py | 20 |
3 files changed, 32 insertions, 4 deletions
diff --git a/docs/index.rst b/docs/index.rst index 27e429c..ac006a8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -251,9 +251,14 @@ The :class:`Future` class encapulates the asynchronous execution of a callable. Attaches the callable *fn* to the future. *fn* will be called, with the future as its only argument, when the future is cancelled or finishes - running. Added callables are called in the order that they were added and are - always called in a thread belonging to the process that added them. - + running. + + Added callables are called in the order that they were added and are always + called in a thread belonging to the process that added them. If the callable + raises an :exc:`Exception` then it will be logged and ignored. If the + callable raises another :exc:`BaseException` then the behavior is not + defined. + If the future has already completed or been cancelled then *fn* will be called immediately. diff --git a/python3/futures/_base.py b/python3/futures/_base.py index 7efc48b..c1181e9 100644 --- a/python3/futures/_base.py +++ b/python3/futures/_base.py @@ -261,7 +261,10 @@ class Future(object): def _invoke_callbacks(self): for callback in self._done_callbacks: - callback(self) + try: + callback(self) + except Exception: + LOGGER.exception('exception calling callback for %r', self) def __repr__(self): with self._condition: diff --git a/python3/test_futures.py b/python3/test_futures.py index b032769..666adbf 100644 --- a/python3/test_futures.py +++ b/python3/test_futures.py @@ -618,6 +618,26 @@ class FutureTests(unittest.TestCase): self.assertTrue(f.cancel()) self.assertTrue(was_cancelled) + def test_done_callback_raises(self): + raising_was_called = False + fn_was_called = False + + def raising_fn(callback_future): + nonlocal raising_was_called + raising_was_called = True + raise Exception('doh!') + + def fn(callback_future): + nonlocal fn_was_called + fn_was_called = True + + f = Future() + f.add_done_callback(raising_fn) + f.add_done_callback(fn) + f.set_result(5) + self.assertTrue(raising_was_called) + self.assertTrue(fn_was_called) + def test_done_callback_already_successful(self): callback_result = None def fn(callback_future): |