diff options
author | Zac Medico <zmedico@gentoo.org> | 2020-03-01 13:56:41 -0800 |
---|---|---|
committer | Zac Medico <zmedico@gentoo.org> | 2020-03-01 16:35:51 -0800 |
commit | bab11fcee344df488d2e7f444ea3711ce87669e3 (patch) | |
tree | b0f0f52a7ef6f64d0915b481d9fe28aedfe9eb5b /lib/_emerge | |
parent | SpawnProcess: cancel _main_task in _unregister (bug 711174) (diff) | |
download | portage-bab11fcee344df488d2e7f444ea3711ce87669e3.tar.gz portage-bab11fcee344df488d2e7f444ea3711ce87669e3.tar.bz2 portage-bab11fcee344df488d2e7f444ea3711ce87669e3.zip |
_GeneratorTask: throw CancelledError in cancelled coroutine (bug 711174)
Throw asyncio.CancelledError in a cancelled coroutine, ensuring
that the coroutine can handle this exception in order to perform
any necessary cleanup (like close the log file for bug 711174).
Note that the asyncio.CancelledError will only be thrown in the
coroutine if there's an opportunity (yield) before the generator
raises StopIteration.
Also fix the AsynchronousTask exit listener handling for
compatibility with this new behavior.
Fixes: 8074127bbc21 ("SpawnProcess: add _main coroutine")
Bug: https://bugs.gentoo.org/711174
Signed-off-by: Zac Medico <zmedico@gentoo.org>
Diffstat (limited to 'lib/_emerge')
-rw-r--r-- | lib/_emerge/AsynchronousTask.py | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/lib/_emerge/AsynchronousTask.py b/lib/_emerge/AsynchronousTask.py index 1e9e177cb..580eef050 100644 --- a/lib/_emerge/AsynchronousTask.py +++ b/lib/_emerge/AsynchronousTask.py @@ -64,7 +64,7 @@ class AsynchronousTask(SlotObject): @returns: Future, result is self.returncode """ waiter = self.scheduler.create_future() - exit_listener = lambda self: waiter.set_result(self.returncode) + exit_listener = lambda self: waiter.cancelled() or waiter.set_result(self.returncode) self.addExitListener(exit_listener) waiter.add_done_callback(lambda waiter: self.removeExitListener(exit_listener) if waiter.cancelled() else None) @@ -180,9 +180,15 @@ class AsynchronousTask(SlotObject): def removeExitListener(self, f): if self._exit_listeners is None: if self._exit_listener_stack is not None: - self._exit_listener_stack.remove(f) + try: + self._exit_listener_stack.remove(f) + except ValueError: + pass return - self._exit_listeners.remove(f) + try: + self._exit_listeners.remove(f) + except ValueError: + pass def _wait_hook(self): """ |