commit: c98240fba21b319e27fe595d70c671c9ddfb7fd0 Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Thu Oct 5 08:20:14 2023 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Thu Oct 5 08:21:47 2023 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=c98240fb
AsyncioEventLoop: Put back _ChildWatcherThreadSafetyWrapper In case there are multiple loops running in different threads, use _ChildWatcherThreadSafetyWrapper. This partially reverts commit 690ac6e78c4099e83b84ef11c0b4064b077a8ef0. Bug: https://bugs.gentoo.org/914873 Signed-off-by: Zac Medico <zmedico <AT> gentoo.org> lib/portage/util/_eventloop/asyncio_event_loop.py | 30 ++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/portage/util/_eventloop/asyncio_event_loop.py b/lib/portage/util/_eventloop/asyncio_event_loop.py index fe941b420a..2b21e6dfaf 100644 --- a/lib/portage/util/_eventloop/asyncio_event_loop.py +++ b/lib/portage/util/_eventloop/asyncio_event_loop.py @@ -112,7 +112,7 @@ class AsyncioEventLoop(_AbstractEventLoop): watcher = ThreadedChildWatcher() watcher.attach_loop(self._loop) - self._child_watcher = watcher + self._child_watcher = _ChildWatcherThreadSafetyWrapper(self, watcher) return self._child_watcher @@ -153,3 +153,31 @@ class AsyncioEventLoop(_AbstractEventLoop): except ValueError: # This is intended to fail when not called in the main thread. pass + + +class _ChildWatcherThreadSafetyWrapper: + """ + This class provides safety if multiple loops are running in different threads. + """ + + def __init__(self, loop, real_watcher): + self._loop = loop + self._real_watcher = real_watcher + + def close(self): + pass + + def __enter__(self): + return self + + def __exit__(self, a, b, c): + pass + + def _child_exit(self, pid, status, callback, *args): + self._loop.call_soon_threadsafe(callback, pid, status, *args) + + def add_child_handler(self, pid, callback, *args): + self._real_watcher.add_child_handler(pid, self._child_exit, callback, *args) + + def remove_child_handler(self, pid): + return self._real_watcher.remove_child_handler(pid)
