diff -r c0224ff67cdd Lib/concurrent/futures/_base.py --- a/Lib/concurrent/futures/_base.py Mon Oct 13 10:39:41 2014 +0100 +++ b/Lib/concurrent/futures/_base.py Mon Oct 13 16:45:00 2014 +0100 @@ -332,9 +332,7 @@ return True self._state = CANCELLED - self._condition.notify_all() - self._invoke_callbacks() return True def cancelled(self): @@ -468,9 +466,7 @@ self._state = CANCELLED_AND_NOTIFIED for waiter in self._waiters: waiter.add_cancelled(self) - # self._condition.notify_all() is not necessary because - # self.cancel() triggers a notification. - return False + self._condition.notify_all() elif self._state == PENDING: self._state = RUNNING return True @@ -480,6 +476,10 @@ self._state) raise RuntimeError('Future in unexpected state') + # fall through if state was CANCELLED + self._invoke_callbacks() + return False + def set_result(self, result): """Sets the return value of work associated with the future. diff -r c0224ff67cdd Lib/test/test_concurrent_futures.py --- a/Lib/test/test_concurrent_futures.py Mon Oct 13 10:39:41 2014 +0100 +++ b/Lib/test/test_concurrent_futures.py Mon Oct 13 16:45:00 2014 +0100 @@ -513,6 +513,7 @@ f = Future() f.add_done_callback(fn) self.assertTrue(f.cancel()) + f.set_running_or_notify_cancel() self.assertTrue(was_cancelled) def test_done_callback_raises(self):