commit: 690ac6e78c4099e83b84ef11c0b4064b077a8ef0 Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Thu Oct 5 06:27:27 2023 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Thu Oct 5 06:57:11 2023 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=690ac6e7
Eliminate deprecated asyncio.get_child_watcher() usage Use PidfdChildWatcher if os.pidfd_open is available and works, and otherwise use ThreadedChildWatcher which should work in any case. The _ChildWatcherThreadSafetyWrapper class is not needed because both PidfdChildWatcher and ThreadedChildWatcher use the running event loop to invoke the child handler callback, and it is safe to assume that the current AsyncioEventLoop instance is the running loop when it is used to obtain a child watcher instance. Bug: https://bugs.gentoo.org/914873 Signed-off-by: Zac Medico <zmedico <AT> gentoo.org> lib/portage/util/_eventloop/asyncio_event_loop.py | 51 +++++++++++------------ 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/lib/portage/util/_eventloop/asyncio_event_loop.py b/lib/portage/util/_eventloop/asyncio_event_loop.py index 37b5b2706c..fe941b420a 100644 --- a/lib/portage/util/_eventloop/asyncio_event_loop.py +++ b/lib/portage/util/_eventloop/asyncio_event_loop.py @@ -6,6 +6,12 @@ import signal import asyncio as _real_asyncio from asyncio.events import AbstractEventLoop as _AbstractEventLoop +from asyncio.unix_events import ThreadedChildWatcher + +try: + from asyncio.unix_events import PidfdChildWatcher +except ImportError: + PidfdChildWatcher = None import portage @@ -90,9 +96,24 @@ class AsyncioEventLoop(_AbstractEventLoop): @return: the internal event loop's AbstractChildWatcher interface """ if self._child_watcher is None: - self._child_watcher = _ChildWatcherThreadSafetyWrapper( - self, _real_asyncio.get_child_watcher() - ) + pidfd_works = False + if PidfdChildWatcher is not None and hasattr(os, "pidfd_open"): + try: + fd = os.pidfd_open(portage.getpid()) + except Exception: + pass + else: + os.close(fd) + pidfd_works = True + + if pidfd_works: + watcher = PidfdChildWatcher() + else: + watcher = ThreadedChildWatcher() + + watcher.attach_loop(self._loop) + self._child_watcher = watcher + return self._child_watcher @property @@ -132,27 +153,3 @@ class AsyncioEventLoop(_AbstractEventLoop): except ValueError: # This is intended to fail when not called in the main thread. pass - - -class _ChildWatcherThreadSafetyWrapper: - 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)
