]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-98023: Change default child watcher to PidfdChildWatcher on supported systems...
authorKumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
Sat, 8 Oct 2022 00:29:09 +0000 (05:59 +0530)
committerGitHub <noreply@github.com>
Sat, 8 Oct 2022 00:29:09 +0000 (17:29 -0700)
Lib/asyncio/unix_events.py
Lib/test/test_asyncio/test_unix_events.py
Misc/NEWS.d/next/Library/2022-10-07-09-52-37.gh-issue-98023.aliEcl.rst [new file with mode: 0644]

index 0f67b4d469f28c0f52bbf65cdf192afd7c0d6637..7fc75cd17ef7415717b6a48a308a889b54020932 100644 (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)
 
index 5bad21ecbae4afa6512361a4d787299ad46dbf93..03fb5e649d8e9741e6aef6d907934534493a4308 100644 (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()
diff --git a/Misc/NEWS.d/next/Library/2022-10-07-09-52-37.gh-issue-98023.aliEcl.rst b/Misc/NEWS.d/next/Library/2022-10-07-09-52-37.gh-issue-98023.aliEcl.rst
new file mode 100644 (file)
index 0000000..1bfd68d
--- /dev/null
@@ -0,0 +1 @@
+Change default child watcher to :class:`~asyncio.PidfdChildWatcher` on Linux systems which supports it. Patch by Kumar Aditya.