aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Lib/asyncio/unix_events.py
diff options
context:
space:
mode:
authorThomas Grainger <tagrain@gmail.com>2022-10-08 01:24:01 +0100
committerGitHub <noreply@github.com>2022-10-07 17:24:01 -0700
commit3d8b22454728b6d54cc476cfb59e47ab40f3f527 (patch)
tree32f85c6b66f858a5235408a1b2b3b4de98b6a7f1 /Lib/asyncio/unix_events.py
parent27ce45d8e105d0c9f9286c3cab830590d4c7cea3 (diff)
downloadcpython-3d8b22454728b6d54cc476cfb59e47ab40f3f527.tar.gz
cpython-3d8b22454728b6d54cc476cfb59e47ab40f3f527.zip
GH-94182: Run the PidfdChildWatcher on the running loop (#94184)
There is no reason for this watcher to be attached to any particular loop. This should make it safe to use regardless of the lifetime of the event loop running in the main thread (relative to other loops). Co-authored-by: Yury Selivanov <yury@edgedb.com> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Diffstat (limited to 'Lib/asyncio/unix_events.py')
-rw-r--r--Lib/asyncio/unix_events.py44
1 files changed, 12 insertions, 32 deletions
diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py
index 96e6d73a759..0f67b4d469f 100644
--- a/Lib/asyncio/unix_events.py
+++ b/Lib/asyncio/unix_events.py
@@ -912,10 +912,6 @@ class PidfdChildWatcher(AbstractChildWatcher):
recent (5.3+) kernels.
"""
- def __init__(self):
- self._loop = None
- self._callbacks = {}
-
def __enter__(self):
return self
@@ -923,35 +919,22 @@ class PidfdChildWatcher(AbstractChildWatcher):
pass
def is_active(self):
- return self._loop is not None and self._loop.is_running()
+ return True
def close(self):
- self.attach_loop(None)
+ pass
def attach_loop(self, loop):
- if self._loop is not None and loop is None and self._callbacks:
- warnings.warn(
- 'A loop is being detached '
- 'from a child watcher with pending handlers',
- RuntimeWarning)
- for pidfd, _, _ in self._callbacks.values():
- self._loop._remove_reader(pidfd)
- os.close(pidfd)
- self._callbacks.clear()
- self._loop = loop
+ pass
def add_child_handler(self, pid, callback, *args):
- existing = self._callbacks.get(pid)
- if existing is not None:
- self._callbacks[pid] = existing[0], callback, args
- else:
- pidfd = os.pidfd_open(pid)
- self._loop._add_reader(pidfd, self._do_wait, pid)
- self._callbacks[pid] = pidfd, callback, args
+ loop = events.get_running_loop()
+ pidfd = os.pidfd_open(pid)
+ loop._add_reader(pidfd, self._do_wait, pid, pidfd, callback, args)
- def _do_wait(self, pid):
- pidfd, callback, args = self._callbacks.pop(pid)
- self._loop._remove_reader(pidfd)
+ def _do_wait(self, pid, pidfd, callback, args):
+ loop = events.get_running_loop()
+ loop._remove_reader(pidfd)
try:
_, status = os.waitpid(pid, 0)
except ChildProcessError:
@@ -969,12 +952,9 @@ class PidfdChildWatcher(AbstractChildWatcher):
callback(pid, returncode, *args)
def remove_child_handler(self, pid):
- try:
- pidfd, _, _ = self._callbacks.pop(pid)
- except KeyError:
- return False
- self._loop._remove_reader(pidfd)
- os.close(pidfd)
+ # asyncio never calls remove_child_handler() !!!
+ # The method is no-op but is implemented because
+ # abstract base classes require it.
return True