summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/whatsnew/3.12.rst18
-rw-r--r--Lib/asyncio/unix_events.py15
-rw-r--r--Lib/test/test_asyncio/test_events.py10
-rw-r--r--Lib/test/test_asyncio/test_streams.py6
-rw-r--r--Lib/test/test_asyncio/test_subprocess.py48
-rw-r--r--Lib/test/test_asyncio/test_unix_events.py21
-rw-r--r--Misc/NEWS.d/next/Library/2022-10-08-06-59-46.gh-issue-94597.TsS0oT.rst1
7 files changed, 81 insertions, 38 deletions
diff --git a/Doc/whatsnew/3.12.rst b/Doc/whatsnew/3.12.rst
index 341e851..9035332 100644
--- a/Doc/whatsnew/3.12.rst
+++ b/Doc/whatsnew/3.12.rst
@@ -109,6 +109,24 @@ New Modules
Improved Modules
================
+asyncio
+-------
+
+* On Linux, :mod:`asyncio` uses :class:`~asyncio.PidfdChildWatcher` by default
+ if :func:`os.pidfd_open` is available and functional instead of
+ :class:`~asyncio.ThreadedChildWatcher`.
+ (Contributed by Kumar Aditya in :gh:`98024`.)
+
+* The child watcher classes :class:`~asyncio.MultiLoopChildWatcher`,
+ :class:`~asyncio.FastChildWatcher` and
+ :class:`~asyncio.SafeChildWatcher` are deprecated and
+ will be removed in Python 3.14. It is recommended to not manually
+ configure a child watcher as the event loop now uses the best available
+ child watcher for each platform (:class:`~asyncio.PidfdChildWatcher`
+ if supported and :class:`~asyncio.ThreadedChildWatcher` otherwise).
+ (Contributed by Kumar Aditya in :gh:`94597`.)
+
+
pathlib
-------
diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py
index 7fc75cd..bdffc03 100644
--- a/Lib/asyncio/unix_events.py
+++ b/Lib/asyncio/unix_events.py
@@ -1022,6 +1022,13 @@ class SafeChildWatcher(BaseChildWatcher):
big number of children (O(n) each time SIGCHLD is raised)
"""
+ def __init__(self):
+ super().__init__()
+ warnings._deprecated("SafeChildWatcher",
+ "{name!r} is deprecated as of Python 3.12 and will be "
+ "removed in Python {remove}.",
+ remove=(3, 14))
+
def close(self):
self._callbacks.clear()
super().close()
@@ -1100,6 +1107,10 @@ class FastChildWatcher(BaseChildWatcher):
self._lock = threading.Lock()
self._zombies = {}
self._forks = 0
+ warnings._deprecated("FastChildWatcher",
+ "{name!r} is deprecated as of Python 3.12 and will be "
+ "removed in Python {remove}.",
+ remove=(3, 14))
def close(self):
self._callbacks.clear()
@@ -1212,6 +1223,10 @@ class MultiLoopChildWatcher(AbstractChildWatcher):
def __init__(self):
self._callbacks = {}
self._saved_sighandler = None
+ warnings._deprecated("MultiLoopChildWatcher",
+ "{name!r} is deprecated as of Python 3.12 and will be "
+ "removed in Python {remove}.",
+ remove=(3, 14))
def is_active(self):
return self._saved_sighandler is not None
diff --git a/Lib/test/test_asyncio/test_events.py b/Lib/test/test_asyncio/test_events.py
index 80d7152..98b55de 100644
--- a/Lib/test/test_asyncio/test_events.py
+++ b/Lib/test/test_asyncio/test_events.py
@@ -22,7 +22,7 @@ import errno
import unittest
from unittest import mock
import weakref
-
+import warnings
if sys.platform not in ('win32', 'vxworks'):
import tty
@@ -2055,7 +2055,9 @@ else:
class UnixEventLoopTestsMixin(EventLoopTestsMixin):
def setUp(self):
super().setUp()
- watcher = asyncio.SafeChildWatcher()
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ watcher = asyncio.SafeChildWatcher()
watcher.attach_loop(self.loop)
asyncio.set_child_watcher(watcher)
@@ -2652,7 +2654,9 @@ class GetEventLoopTestsMixin:
asyncio.set_event_loop(self.loop)
if sys.platform != 'win32':
- watcher = asyncio.SafeChildWatcher()
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ watcher = asyncio.SafeChildWatcher()
watcher.attach_loop(self.loop)
asyncio.set_child_watcher(watcher)
diff --git a/Lib/test/test_asyncio/test_streams.py b/Lib/test/test_asyncio/test_streams.py
index 0c49099..8fb9313 100644
--- a/Lib/test/test_asyncio/test_streams.py
+++ b/Lib/test/test_asyncio/test_streams.py
@@ -9,6 +9,7 @@ import sys
import threading
import unittest
from unittest import mock
+import warnings
from test.support import socket_helper
try:
import ssl
@@ -791,8 +792,9 @@ os.close(fd)
protocol = asyncio.StreamReaderProtocol(reader, loop=self.loop)
transport, _ = self.loop.run_until_complete(
self.loop.connect_read_pipe(lambda: protocol, pipe))
-
- watcher = asyncio.SafeChildWatcher()
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', DeprecationWarning)
+ watcher = asyncio.SafeChildWatcher()
watcher.attach_loop(self.loop)
try:
asyncio.set_child_watcher(watcher)
diff --git a/Lib/test/test_asyncio/test_subprocess.py b/Lib/test/test_asyncio/test_subprocess.py
index 6ba8894..915ad55 100644
--- a/Lib/test/test_asyncio/test_subprocess.py
+++ b/Lib/test/test_asyncio/test_subprocess.py
@@ -4,7 +4,6 @@ import signal
import sys
import unittest
import warnings
-import functools
from unittest import mock
import asyncio
@@ -31,19 +30,6 @@ PROGRAM_CAT = [
'sys.stdout.buffer.write(data)'))]
-@functools.cache
-def _has_pidfd_support():
- if not hasattr(os, 'pidfd_open'):
- return False
-
- try:
- os.close(os.pidfd_open(os.getpid()))
- except OSError:
- return False
-
- return True
-
-
def tearDownModule():
asyncio.set_event_loop_policy(None)
@@ -688,7 +674,7 @@ if sys.platform != 'win32':
self.loop = policy.new_event_loop()
self.set_event_loop(self.loop)
- watcher = self.Watcher()
+ watcher = self._get_watcher()
watcher.attach_loop(self.loop)
policy.set_child_watcher(watcher)
@@ -703,32 +689,38 @@ if sys.platform != 'win32':
class SubprocessThreadedWatcherTests(SubprocessWatcherMixin,
test_utils.TestCase):
- Watcher = unix_events.ThreadedChildWatcher
-
- @unittest.skip("bpo-38323: MultiLoopChildWatcher has a race condition \
- and these tests can hang the test suite")
- class SubprocessMultiLoopWatcherTests(SubprocessWatcherMixin,
- test_utils.TestCase):
-
- Watcher = unix_events.MultiLoopChildWatcher
+ def _get_watcher(self):
+ return unix_events.ThreadedChildWatcher()
class SubprocessSafeWatcherTests(SubprocessWatcherMixin,
test_utils.TestCase):
- Watcher = unix_events.SafeChildWatcher
+ def _get_watcher(self):
+ with self.assertWarns(DeprecationWarning):
+ return unix_events.SafeChildWatcher()
+
+ class MultiLoopChildWatcherTests(test_utils.TestCase):
+
+ def test_warns(self):
+ with self.assertWarns(DeprecationWarning):
+ unix_events.MultiLoopChildWatcher()
class SubprocessFastWatcherTests(SubprocessWatcherMixin,
test_utils.TestCase):
- Watcher = unix_events.FastChildWatcher
+ def _get_watcher(self):
+ with self.assertWarns(DeprecationWarning):
+ return unix_events.FastChildWatcher()
@unittest.skipUnless(
- _has_pidfd_support(),
+ unix_events.can_use_pidfd(),
"operating system does not support pidfds",
)
class SubprocessPidfdWatcherTests(SubprocessWatcherMixin,
test_utils.TestCase):
- Watcher = unix_events.PidfdChildWatcher
+
+ def _get_watcher(self):
+ return unix_events.PidfdChildWatcher()
class GenericWatcherTests(test_utils.TestCase):
@@ -758,7 +750,7 @@ if sys.platform != 'win32':
@unittest.skipUnless(
- _has_pidfd_support(),
+ unix_events.can_use_pidfd(),
"operating system does not support pidfds",
)
def test_create_subprocess_with_pidfd(self):
diff --git a/Lib/test/test_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py
index 03fb5e6..025da0f 100644
--- a/Lib/test/test_asyncio/test_unix_events.py
+++ b/Lib/test/test_asyncio/test_unix_events.py
@@ -12,6 +12,7 @@ import sys
import threading
import unittest
from unittest import mock
+import warnings
from test.support import os_helper
from test.support import socket_helper
@@ -1686,12 +1687,16 @@ class ChildWatcherTestsMixin:
class SafeChildWatcherTests (ChildWatcherTestsMixin, test_utils.TestCase):
def create_watcher(self):
- return asyncio.SafeChildWatcher()
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ return asyncio.SafeChildWatcher()
class FastChildWatcherTests (ChildWatcherTestsMixin, test_utils.TestCase):
def create_watcher(self):
- return asyncio.FastChildWatcher()
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ return asyncio.FastChildWatcher()
class PolicyTests(unittest.TestCase):
@@ -1724,7 +1729,9 @@ class PolicyTests(unittest.TestCase):
def test_get_child_watcher_after_set(self):
policy = self.create_policy()
- watcher = asyncio.FastChildWatcher()
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ watcher = asyncio.FastChildWatcher()
policy.set_child_watcher(watcher)
self.assertIs(policy._watcher, watcher)
@@ -1745,7 +1752,9 @@ class PolicyTests(unittest.TestCase):
policy.get_event_loop().close()
policy = self.create_policy()
- policy.set_child_watcher(asyncio.SafeChildWatcher())
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ policy.set_child_watcher(asyncio.SafeChildWatcher())
th = threading.Thread(target=f)
th.start()
@@ -1757,7 +1766,9 @@ class PolicyTests(unittest.TestCase):
# Explicitly setup SafeChildWatcher,
# default ThreadedChildWatcher has no _loop property
- watcher = asyncio.SafeChildWatcher()
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ watcher = asyncio.SafeChildWatcher()
policy.set_child_watcher(watcher)
watcher.attach_loop(loop)
diff --git a/Misc/NEWS.d/next/Library/2022-10-08-06-59-46.gh-issue-94597.TsS0oT.rst b/Misc/NEWS.d/next/Library/2022-10-08-06-59-46.gh-issue-94597.TsS0oT.rst
new file mode 100644
index 0000000..f504ccf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-10-08-06-59-46.gh-issue-94597.TsS0oT.rst
@@ -0,0 +1 @@
+The child watcher classes :class:`~asyncio.MultiLoopChildWatcher`, :class:`~asyncio.FastChildWatcher` and :class:`~asyncio.SafeChildWatcher` are deprecated and will be removed in Python 3.14. Patch by Kumar Aditya.