GH-98023: Change default child watcher to PidfdChildWatcher on supported systems (#98024)

This commit is contained in:
Kumar Aditya 2022-10-08 05:59:09 +05:30 committed by GitHub
parent 3d8b224547
commit 8ba9378b16
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 2 deletions

View file

@ -1403,6 +1403,17 @@ class ThreadedChildWatcher(AbstractChildWatcher):
self._threads.pop(expected_pid)
def can_use_pidfd():
if not hasattr(os, 'pidfd_open'):
return False
try:
pid = os.getpid()
os.close(os.pidfd_open(pid, 0))
except OSError:
# blocked by security policy like SECCOMP
return False
return True
class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
"""UNIX event loop policy with a watcher for child processes."""
@ -1415,7 +1426,10 @@ class _UnixDefaultEventLoopPolicy(events.BaseDefaultEventLoopPolicy):
def _init_watcher(self):
with events._lock:
if self._watcher is None: # pragma: no branch
self._watcher = ThreadedChildWatcher()
if can_use_pidfd():
self._watcher = PidfdChildWatcher()
else:
self._watcher = ThreadedChildWatcher()
if threading.current_thread() is threading.main_thread():
self._watcher.attach_loop(self._local._loop)

View file

@ -1702,7 +1702,8 @@ class PolicyTests(unittest.TestCase):
def test_get_default_child_watcher(self):
policy = self.create_policy()
self.assertIsNone(policy._watcher)
unix_events.can_use_pidfd = mock.Mock()
unix_events.can_use_pidfd.return_value = False
watcher = policy.get_child_watcher()
self.assertIsInstance(watcher, asyncio.ThreadedChildWatcher)
@ -1710,6 +1711,17 @@ class PolicyTests(unittest.TestCase):
self.assertIs(watcher, policy.get_child_watcher())
policy = self.create_policy()
self.assertIsNone(policy._watcher)
unix_events.can_use_pidfd = mock.Mock()
unix_events.can_use_pidfd.return_value = True
watcher = policy.get_child_watcher()
self.assertIsInstance(watcher, asyncio.PidfdChildWatcher)
self.assertIs(policy._watcher, watcher)
self.assertIs(watcher, policy.get_child_watcher())
def test_get_child_watcher_after_set(self):
policy = self.create_policy()
watcher = asyncio.FastChildWatcher()

View file

@ -0,0 +1 @@
Change default child watcher to :class:`~asyncio.PidfdChildWatcher` on Linux systems which supports it. Patch by Kumar Aditya.