Package: src:multiprocess
Version: 0.70.19-2
User: [email protected]
Usertags: python3.15
Tags: patch, ftbfs, forky, sid

Hi!

While rebuilding the python related packages against the Python 3.15rc1
version we found that multiprocess fails to build from source [1].
This is due to the fact that the upstream code vendors the cpython tests
shipped in each version, this needs to be updated on every python
release.

In order to fix the issue, I had to apply these upstream fixes:
 - 0001-sync-with-python-3.15.0a6.patch (commit 10255c452049)
 - 0002-sync-with-python-3.15.0a7.patch (commit f194e2b19627)
 - 0003-sync-3.13.13.-3.14.4-3.15.0a8.patch (commit f3bafd97de2e)
 - 0004-sync-with-3.14.5-and-3.15.0b1.patch (commit 4dd9bed7b1e5)
 - 0005-sync-with-python-3.15.0b2.patch (commit 982f27e16754)
 - 0006-sync-with-python-3.15.0b4.patch (commit 707f56485a0e)
 - 0007-sync-with-3.14.7-and-3.15.0rc1.patch (commit 0ae73b4187cc)
 - 0008-sync-with-3.15.0rc2.patch (commit af6e5ba1871a)
It would be better to avoid doing this constant catch up with the python
releases.

I applied these fixes in the sandbox [2] to be able to build the
packages that depend on multiprocess, please consider applying the
patches to support the upcoming 3.15 version.

Happy hacking,

[1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/4349814/
[2]: https://debusine.debian.net/debian/r-python-python3.15/

--
"Can you imagine what I would do if I could do all I can?" -- Sun Tzu
Saludos /\/\ /\ >< `/
From: Mike McKerns <[email protected]>
Date: Fri, 13 Feb 2026 20:37:42 -0500
Subject: sync with python 3.15.0a6 (#252)

---
diff --git a/py3.15/multiprocess/context.py b/py3.15/multiprocess/context.py
index 773858d..564462b 100644
--- a/py3.15/multiprocess/context.py
+++ b/py3.15/multiprocess/context.py
@@ -177,12 +177,15 @@ class BaseContext(object):
         from .spawn import set_executable
         set_executable(executable)
 
-    def set_forkserver_preload(self, module_names):
+    def set_forkserver_preload(self, module_names, *, on_error='ignore'):
         '''Set list of module names to try to load in forkserver process.
-        This is really just a hint.
+
+        The on_error parameter controls how import failures are handled:
+        "ignore" (default) silently ignores failures, "warn" emits warnings,
+        and "fail" raises exceptions breaking the forkserver context.
         '''
         from .forkserver import set_forkserver_preload
-        set_forkserver_preload(module_names)
+        set_forkserver_preload(module_names, on_error=on_error)
 
     def get_context(self, method=None):
         if method is None:
diff --git a/py3.15/multiprocess/forkserver.py b/py3.15/multiprocess/forkserver.py
index 822be32..f16352e 100644
--- a/py3.15/multiprocess/forkserver.py
+++ b/py3.15/multiprocess/forkserver.py
@@ -42,6 +42,7 @@ class ForkServer(object):
         self._inherited_fds = None
         self._lock = threading.Lock()
         self._preload_modules = ['__main__']
+        self._preload_on_error = 'ignore'
 
     def _stop(self):
         # Method used by unit tests to stop the server
@@ -64,11 +65,22 @@ class ForkServer(object):
         self._forkserver_address = None
         self._forkserver_authkey = None
 
-    def set_forkserver_preload(self, modules_names):
-        '''Set list of module names to try to load in forkserver process.'''
+    def set_forkserver_preload(self, modules_names, *, on_error='ignore'):
+        '''Set list of module names to try to load in forkserver process.
+
+        The on_error parameter controls how import failures are handled:
+        "ignore" (default) silently ignores failures, "warn" emits warnings,
+        and "fail" raises exceptions breaking the forkserver context.
+        '''
         if not all(type(mod) is str for mod in modules_names):
             raise TypeError('module_names must be a list of strings')
+        if on_error not in ('ignore', 'warn', 'fail'):
+            raise ValueError(
+                f"on_error must be 'ignore', 'warn', or 'fail', "
+                f"not {on_error!r}"
+            )
         self._preload_modules = modules_names
+        self._preload_on_error = on_error
 
     def get_inherited_fds(self):
         '''Return list of fds inherited from parent process.
@@ -107,6 +119,14 @@ class ForkServer(object):
                             wrapped_client, self._forkserver_authkey)
                     connection.deliver_challenge(
                             wrapped_client, self._forkserver_authkey)
+                except (EOFError, ConnectionError, BrokenPipeError) as exc:
+                    if (self._preload_modules and
+                        self._preload_on_error == 'fail'):
+                        exc.add_note( 
+                            "Forkserver process may have crashed during module "
+                            "preloading. Check stderr."
+                        )
+                    raise
                 finally:
                     wrapped_client._detach()
                     del wrapped_client
@@ -154,6 +174,8 @@ class ForkServer(object):
                     main_kws['main_path'] = data['init_main_from_path']
                 if 'sys_argv' in data:
                     main_kws['sys_argv'] = data['sys_argv']
+                if self._preload_on_error != 'ignore':
+                    main_kws['on_error'] = self._preload_on_error
 
             with socket.socket(socket.AF_UNIX) as listener:
                 address = connection.arbitrary_address('AF_UNIX')
@@ -198,8 +220,69 @@ class ForkServer(object):
 #
 #
 
+def _handle_import_error(on_error, modinfo, exc, *, warn_stacklevel):
+    """Handle an import error according to the on_error policy."""
+    match on_error:     
+        case 'fail':
+            raise
+        case 'warn':
+            warnings.warn(
+                f"Failed to preload {modinfo}: {exc}",
+                ImportWarning,
+                stacklevel=warn_stacklevel + 1
+            )   
+        case 'ignore':
+            pass
+
+
+def _handle_preload(preload, main_path=None, sys_path=None, sys_argv=None,
+                    on_error='ignore'):
+    """Handle module preloading with configurable error handling.
+
+    Args:
+        preload: List of module names to preload.
+        main_path: Path to __main__ module if '__main__' is in preload.
+        sys_path: sys.path to use for imports (None means use current).
+        sys_argv: sys.argv to use (None means use current).
+        on_error: How to handle import errors ("ignore", "warn", or "fail").
+    """
+    if not preload:
+        return
+
+    if sys_argv is not None:
+        sys.argv[:] = sys_argv
+    if sys_path is not None:
+        sys.path[:] = sys_path
+
+    if '__main__' in preload and main_path is not None:
+        process.current_process()._inheriting = True
+        try:
+            spawn.import_main_path(main_path)
+        except Exception as e:
+            # Catch broad Exception because import_main_path() uses
+            # runpy.run_path() which executes the script and can raise
+            # any exception, not just ImportError
+            _handle_import_error(
+                on_error, f"__main__ from {main_path!r}", e, warn_stacklevel=2
+            )
+        finally:
+            del process.current_process()._inheriting
+
+    for modname in preload:
+        try:
+            __import__(modname)
+        except ImportError as e:
+            _handle_import_error(
+                on_error, f"module {modname!r}", e, warn_stacklevel=2
+            )
+
+    # gh-135335: flush stdout/stderr in case any of the preloaded modules
+    # wrote to them, otherwise children might inherit buffered data
+    util._flush_std_streams()
+
+
 def main(listener_fd, alive_r, preload, main_path=None, sys_path=None,
-         *, sys_argv=None, authkey_r=None):
+         *, sys_argv=None, authkey_r=None, on_error='ignore'):
     """Run forkserver."""
     if authkey_r is not None:
         try:
@@ -210,26 +293,7 @@ def main(listener_fd, alive_r, preload, main_path=None, sys_path=None,
     else:
         authkey = b''
 
-    if preload:
-        if sys_argv is not None:
-            sys.argv[:] = sys_argv
-        if sys_path is not None:
-            sys.path[:] = sys_path
-        if '__main__' in preload and main_path is not None:
-            process.current_process()._inheriting = True
-            try:
-                spawn.import_main_path(main_path)
-            finally:
-                del process.current_process()._inheriting
-        for modname in preload:
-            try:
-                __import__(modname)
-            except ImportError:
-                pass
-
-        # gh-135335: flush stdout/stderr in case any of the preloaded modules
-        # wrote to them, otherwise children might inherit buffered data
-        util._flush_std_streams()
+    _handle_preload(preload, main_path, sys_path, sys_argv, on_error)
 
     util._close_stdin()
 
From: Mike McKerns <[email protected]>
Date: Sun, 22 Mar 2026 18:20:44 -0600
Subject: sync with python 3.15.0a7 (#253)

---
diff --git a/py3.15/multiprocess/connection.py b/py3.15/multiprocess/connection.py
index 1254c91..9a22f66 100644
--- a/py3.15/multiprocess/connection.py
+++ b/py3.15/multiprocess/connection.py
@@ -49,6 +49,7 @@ BUFSIZE = 64 * 1024
 CONNECTION_TIMEOUT = 20.
 
 _mmap_counter = itertools.count()
+_MAX_PIPE_ATTEMPTS = 100
 
 default_family = 'AF_INET'
 families = ['AF_INET']
@@ -81,8 +82,8 @@ def arbitrary_address(family):
     elif family == 'AF_UNIX':
         return tempfile.mktemp(prefix='sock-', dir=util.get_temp_dir())
     elif family == 'AF_PIPE':
-        return tempfile.mktemp(prefix=r'\\.\pipe\pyc-%d-%d-' %
-                               (os.getpid(), next(_mmap_counter)), dir="")
+        return (r'\\.\pipe\pyc-%d-%d-%s' %
+                (os.getpid(), next(_mmap_counter), os.urandom(8).hex()))
     else:
         raise ValueError('unrecognized family')
 
@@ -475,17 +476,29 @@ class Listener(object):
     def __init__(self, address=None, family=None, backlog=1, authkey=None):
         family = family or (address and address_type(address)) \
                  or default_family
-        address = address or arbitrary_address(family)
-
         _validate_family(family)
+        if authkey is not None and not isinstance(authkey, bytes):
+            raise TypeError('authkey should be a byte string')
+
         if family == 'AF_PIPE':
-            self._listener = PipeListener(address, backlog)
+            if address:
+                self._listener = PipeListener(address, backlog)
+            else:
+                for attempts in itertools.count():
+                    address = arbitrary_address(family) 
+                    try:
+                        self._listener = PipeListener(address, backlog)
+                        break
+                    except OSError as e:
+                        if attempts >= _MAX_PIPE_ATTEMPTS:
+                            raise
+                        if e.winerror not in (_winapi.ERROR_PIPE_BUSY,
+                                              _winapi.ERROR_ACCESS_DENIED):
+                            raise
         else:
+            address = address or arbitrary_address(family)
             self._listener = SocketListener(address, family, backlog)
 
-        if authkey is not None and not isinstance(authkey, bytes):
-            raise TypeError('authkey should be a byte string')
-
         self._authkey = authkey
 
     def accept(self):
@@ -573,7 +586,6 @@ else:
         '''
         Returns pair of connection objects at either end of a pipe
         '''
-        address = arbitrary_address('AF_PIPE')
         if duplex:
             openmode = _winapi.PIPE_ACCESS_DUPLEX
             access = _winapi.GENERIC_READ | _winapi.GENERIC_WRITE
@@ -583,15 +595,25 @@ else:
             access = _winapi.GENERIC_WRITE
             obsize, ibsize = 0, BUFSIZE
 
-        h1 = _winapi.CreateNamedPipe(
-            address, openmode | _winapi.FILE_FLAG_OVERLAPPED |
-            _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE,
-            _winapi.PIPE_TYPE_MESSAGE | _winapi.PIPE_READMODE_MESSAGE |
-            _winapi.PIPE_WAIT,
-            1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER,
-            # default security descriptor: the handle cannot be inherited
-            _winapi.NULL
-            )
+        for attempts in itertools.count():
+            address = arbitrary_address('AF_PIPE')
+            try:
+                h1 = _winapi.CreateNamedPipe(
+                    address, openmode | _winapi.FILE_FLAG_OVERLAPPED |
+                    _winapi.FILE_FLAG_FIRST_PIPE_INSTANCE,
+                    _winapi.PIPE_TYPE_MESSAGE | _winapi.PIPE_READMODE_MESSAGE |
+                    _winapi.PIPE_WAIT,
+                    1, obsize, ibsize, _winapi.NMPWAIT_WAIT_FOREVER,
+                    # default security descriptor: the handle cannot be inherited
+                    _winapi.NULL
+                    )
+                break
+            except OSError as e:
+                if attempts >= _MAX_PIPE_ATTEMPTS:
+                    raise
+                if e.winerror not in (_winapi.ERROR_PIPE_BUSY,
+                                      _winapi.ERROR_ACCESS_DENIED):
+                    raise
         h2 = _winapi.CreateFile(
             address, access, 0, _winapi.NULL, _winapi.OPEN_EXISTING,
             _winapi.FILE_FLAG_OVERLAPPED, _winapi.NULL
From: Mike McKerns <[email protected]>
Date: Sun, 12 Apr 2026 05:18:55 -0400
Subject: sync 3.13.13. 3.14.4 3.15.0a8 (#256)

---
diff --git a/py3.15/Modules/_multiprocess/multiprocess.c b/py3.15/Modules/_multiprocess/multiprocess.c
index 810b826..4cc9cee 100644
--- a/py3.15/Modules/_multiprocess/multiprocess.c
+++ b/py3.15/Modules/_multiprocess/multiprocess.c
@@ -274,6 +274,7 @@ multiprocess_exec(PyObject *module)
 }
 
 static PyModuleDef_Slot multiprocess_slots[] = {
+    _Py_ABI_SLOT,
     {Py_mod_exec, multiprocess_exec},
     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
     {Py_mod_gil, Py_MOD_GIL_NOT_USED},
diff --git a/py3.15/multiprocess/connection.py b/py3.15/multiprocess/connection.py
index 9a22f66..9f7e039 100644
--- a/py3.15/multiprocess/connection.py
+++ b/py3.15/multiprocess/connection.py
@@ -1089,14 +1089,22 @@ if sys.platform == 'win32':
 
         Returns list of those objects in object_list which are ready/readable.
         '''
+        object_list = list(object_list)
+
+        if not object_list:
+            if timeout is None:
+                while True:
+                    time.sleep(1e6)
+            elif timeout > 0:
+                time.sleep(timeout)
+            return []
+
         if timeout is None:
             timeout = INFINITE
         elif timeout < 0:
             timeout = 0
         else:
             timeout = int(timeout * 1000 + 0.5)
-
-        object_list = list(object_list)
         waithandle_to_obj = {}
         ov_list = []
         ready_objects = set()
diff --git a/py3.15/multiprocess/context.py b/py3.15/multiprocess/context.py
index 564462b..c01bfc9 100644
--- a/py3.15/multiprocess/context.py
+++ b/py3.15/multiprocess/context.py
@@ -145,7 +145,13 @@ class BaseContext(object):
         '''Check whether this is a fake forked process in a frozen executable.
         If so then run code specified by commandline and exit.
         '''
-        if self.get_start_method() == 'spawn' and getattr(sys, 'frozen', False):
+        # gh-140814: allow_none=True avoids locking in the default start
+        # method, which would cause a later set_start_method() to fail.
+        # None is safe to pass through: spawn.freeze_support()
+        # independently detects whether this process is a spawned
+        # child, so the start method check here is only an optimization.
+        if (getattr(sys, 'frozen', False)
+                and self.get_start_method(allow_none=True) in ('spawn', None)):
             from .spawn import freeze_support
             freeze_support()
 
diff --git a/py3.15/multiprocess/forkserver.py b/py3.15/multiprocess/forkserver.py
index f16352e..775f540 100644
--- a/py3.15/multiprocess/forkserver.py
+++ b/py3.15/multiprocess/forkserver.py
@@ -162,10 +162,17 @@ class ForkServer(object):
                 self._forkserver_alive_fd = None
                 self._forkserver_pid = None
 
-            cmd = ('from multiprocess.forkserver import main; ' +
-                   'main(%d, %d, %r, **%r)')
+            # gh-144503: sys_argv is passed as real argv elements after the
+            # ``-c cmd`` rather than repr'd into main_kws so that a large
+            # parent sys.argv cannot push the single ``-c`` command string
+            # over the OS per-argument length limit (MAX_ARG_STRLEN on Linux).
+            # The child sees them as sys.argv[1:].
+            cmd = ('import sys; '
+                   'from multiprocess.forkserver import main; '
+                   'main(%d, %d, %r, sys_argv=sys.argv[1:], **%r)')
 
             main_kws = {}
+            sys_argv = None
             if self._preload_modules:
                 data = spawn.get_preparation_data('ignore')
                 if 'sys_path' in data:
@@ -173,7 +180,7 @@ class ForkServer(object):
                 if 'init_main_from_path' in data:
                     main_kws['main_path'] = data['init_main_from_path']
                 if 'sys_argv' in data:
-                    main_kws['sys_argv'] = data['sys_argv']
+                    sys_argv = data['sys_argv']
                 if self._preload_on_error != 'ignore':
                     main_kws['on_error'] = self._preload_on_error
 
@@ -197,6 +204,8 @@ class ForkServer(object):
                     exe = spawn.get_executable()
                     args = [exe] + util._args_from_interpreter_flags()
                     args += ['-c', cmd]
+                    if sys_argv is not None:
+                        args += sys_argv
                     pid = util.spawnv_passfds(exe, args, fds_to_pass)
                 except:
                     os.close(alive_w)
diff --git a/py3.15/multiprocess/tests/__init__.py b/py3.15/multiprocess/tests/__init__.py
index 36fc4f0..e61949d 100644
--- a/py3.15/multiprocess/tests/__init__.py
+++ b/py3.15/multiprocess/tests/__init__.py
@@ -214,10 +214,38 @@ def only_run_in_spawn_testsuite(reason):
     return decorator
 
 
+def only_run_in_forkserver_testsuite(reason):
+    """Returns a decorator: raises SkipTest unless fork is supported
+    and the current start method is forkserver.
+
+    Combines @support.requires_fork() with the single-run semantics of
+    only_run_in_spawn_testsuite(), but uses the forkserver testsuite as
+    the single-run target.  Appropriate for tests that exercise
+    os.fork() directly (raw fork or mp.set_start_method("fork") in a
+    subprocess) and don't vary by start method, since forkserver is
+    only available on platforms that support fork.
+    """
+
+    def decorator(test_item):
+
+        @functools.wraps(test_item)
+        def forkserver_check_wrapper(*args, **kwargs):
+            if not support.has_fork_support:
+                raise unittest.SkipTest("requires working os.fork()")
+            if (start_method := multiprocessing.get_start_method()) != "forkserver":
+                raise unittest.SkipTest(
+                    f"{start_method=}, not 'forkserver'; {reason}")
+            return test_item(*args, **kwargs)
+
+        return forkserver_check_wrapper
+
+    return decorator
+
+
 class TestInternalDecorators(unittest.TestCase):
     """Logic within a test suite that could errantly skip tests? Test it!"""
 
-    @unittest.skipIf(sys.platform == "win32", "test requires that fork exists.")
+    @support.requires_fork()
     def test_only_run_in_spawn_testsuite(self):
         if multiprocessing.get_start_method() != "spawn":
             raise unittest.SkipTest("only run in test_multiprocessing_spawn.")
@@ -241,6 +269,30 @@ class TestInternalDecorators(unittest.TestCase):
         finally:
             multiprocessing.set_start_method(orig_start_method, force=True)
 
+    @support.requires_fork()
+    def test_only_run_in_forkserver_testsuite(self):
+        if multiprocessing.get_start_method() != "forkserver":
+            raise unittest.SkipTest("only run in test_multiprocessing_forkserver.")
+
+        try:
+            @only_run_in_forkserver_testsuite("testing this decorator")
+            def return_four_if_forkserver():
+                return 4
+        except Exception as err:
+            self.fail(f"expected decorated `def` not to raise; caught {err}")
+
+        orig_start_method = multiprocessing.get_start_method(allow_none=True)
+        try:
+            multiprocessing.set_start_method("forkserver", force=True)
+            self.assertEqual(return_four_if_forkserver(), 4)
+            multiprocessing.set_start_method("spawn", force=True)
+            with self.assertRaises(unittest.SkipTest) as ctx:
+                return_four_if_forkserver()
+            self.assertIn("testing this decorator", str(ctx.exception))
+            self.assertIn("start_method=", str(ctx.exception))
+        finally:
+            multiprocessing.set_start_method(orig_start_method, force=True)
+
 
 #
 # Creates a wrapper for a function which records the time it takes to finish
@@ -3901,6 +3953,19 @@ class _TestConnection(BaseTestCase):
             self.assertRaises(OSError, a.recv)
             self.assertRaises(OSError, b.recv)
 
+    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    def test_wait_empty(self):
+        if self.TYPE != 'processes':
+            self.skipTest('test not appropriate for {}'.format(self.TYPE))
+        # gh-145587: wait() with empty list should respect timeout
+        timeout = 0.5
+        start = time.monotonic()
+        res = self.connection.wait([], timeout=timeout)
+        duration = time.monotonic() - start
+
+        self.assertEqual(res, [])
+        self.assertGreaterEqual(duration, timeout - 0.1)
+
 class _TestListener(BaseTestCase):
 
     ALLOWED_TYPES = ('processes',)
@@ -6005,6 +6070,20 @@ class TestStartMethod(unittest.TestCase):
             process.join()
             self.assertIsNone(multiprocessing.get_start_method(allow_none=True))
 
+    @only_run_in_spawn_testsuite("freeze_support is not start method specific")
+    def test_freeze_support_dont_set_context(self):
+        # gh-140814: freeze_support() should not set the start method
+        # as a side effect, so a later set_start_method() still works.
+        multiprocessing.set_start_method(None, force=True)
+        try:
+            multiprocessing.freeze_support()
+            self.assertIsNone(
+                multiprocessing.get_start_method(allow_none=True))
+            # Should not raise "context has already been set"
+            multiprocessing.set_start_method('spawn')
+        finally:
+            multiprocessing.set_start_method(None, force=True)
+
     def test_context_check_module_types(self):
         try:
             ctx = multiprocessing.get_context('forkserver')
@@ -7126,6 +7205,24 @@ class MiscTestCase(unittest.TestCase):
             '',
         ])
 
+    @unittest.skipIf(sys.hexversion <= 0x30f00a8, "added in 3.15.0a8")
+    @only_run_in_forkserver_testsuite("forkserver specific test.")
+    def test_preload_main_large_sys_argv(self):
+        # gh-144503: a very large parent sys.argv must not prevent the
+        # forkserver from starting (it previously overflowed the OS
+        # per-argument length limit when repr'd into the -c command string).
+        name = os.path.join(os.path.dirname(__file__),
+                            'mp_preload_large_sysargv.py')
+        _, out, err = test.support.script_helper.assert_python_ok(name)
+        self.assertEqual(err, b'')
+    
+        out = out.decode().split("\n")
+        self.assertEqual(out, [
+            'preload:5002:sentinel',
+            'worker:5002:sentinel',
+            '',
+        ])
+
 #
 # Mixins
 #
diff --git a/py3.15/multiprocess/tests/mp_preload_large_sysargv.py b/py3.15/multiprocess/tests/mp_preload_large_sysargv.py
new file mode 100644
index 0000000..790fcd7
--- /dev/null
+++ b/py3.15/multiprocess/tests/mp_preload_large_sysargv.py
@@ -0,0 +1,30 @@
+# gh-144503: Test that the forkserver can start when the parent process has
+# a very large sys.argv.  Prior to the fix, sys.argv was repr'd into the
+# forkserver ``-c`` command string which could exceed the OS limit on the
+# length of a single argv element (MAX_ARG_STRLEN on Linux, ~128 KiB),
+# causing posix_spawn to fail and the parent to see a BrokenPipeError.
+
+import multiprocessing
+import sys
+
+EXPECTED_LEN = 5002  # argv[0] + 5000 padding entries + sentinel
+
+
+def fun():
+    print(f"worker:{len(sys.argv)}:{sys.argv[-1]}")
+
+
+if __name__ == "__main__":
+    # Inflate sys.argv well past 128 KiB before the forkserver is started.
+    sys.argv[1:] = ["x" * 50] * 5000 + ["sentinel"]
+    assert len(sys.argv) == EXPECTED_LEN
+
+    ctx = multiprocessing.get_context("forkserver")
+    p = ctx.Process(target=fun)
+    p.start()
+    p.join()
+    sys.exit(p.exitcode)
+else:
+    # This branch runs when the forkserver preloads this module as
+    # __mp_main__; confirm the large argv was propagated intact.
+    print(f"preload:{len(sys.argv)}:{sys.argv[-1]}")
From: Mike McKerns <[email protected]>
Date: Sat, 23 May 2026 18:01:32 -0400
Subject: sync with 3.14.5 and 3.15.0b1 (#259)

---
diff --git a/py3.15/multiprocess/connection.py b/py3.15/multiprocess/connection.py
index 9f7e039..7c60bd2 100644
--- a/py3.15/multiprocess/connection.py
+++ b/py3.15/multiprocess/connection.py
@@ -16,7 +16,6 @@ import os
 import sys
 import socket
 import struct
-import tempfile
 import time
 
 
@@ -80,7 +79,11 @@ def arbitrary_address(family):
     if family == 'AF_INET':
         return ('localhost', 0)
     elif family == 'AF_UNIX':
-        return tempfile.mktemp(prefix='sock-', dir=util.get_temp_dir())
+        # NOTE: util.get_temp_dir() is a 0o700 per-process directory. A
+        # mktemp-style ToC vs ToU concern is not important; bind() surfaces
+        # the extremely unlikely collision as EADDRINUSE.
+        return os.path.join(util.get_temp_dir(),
+                            f'sock-{os.urandom(6).hex()}')
     elif family == 'AF_PIPE':
         return (r'\\.\pipe\pyc-%d-%d-%s' %
                 (os.getpid(), next(_mmap_counter), os.urandom(8).hex()))
diff --git a/py3.15/multiprocess/popen_fork.py b/py3.15/multiprocess/popen_fork.py
index 710acc9..713145c 100644
--- a/py3.15/multiprocess/popen_fork.py
+++ b/py3.15/multiprocess/popen_fork.py
@@ -67,7 +67,17 @@ class Popen(object):
         code = 1
         parent_r, child_w = os.pipe()
         child_r, parent_w = os.pipe()
-        self.pid = os.fork()
+        # gh-146313: Tell the resource tracker's at-fork handler to keep
+        # the inherited pipe fd so this child reuses the parent's tracker
+        # (gh-80849) rather than closing it and launching its own.
+        from .resource_tracker import _fork_intent
+        _fork_intent.preserve_fd = True
+        try:
+            self.pid = os.fork()
+        finally:
+            # Reset in both parent and child so the flag does not leak
+            # into a subsequent raw os.fork() or nested Process launch.
+            _fork_intent.preserve_fd = False
         if self.pid == 0:
             try:
                 atexit._clear()
diff --git a/py3.15/multiprocess/resource_tracker.py b/py3.15/multiprocess/resource_tracker.py
index 9c635db..5b2c475 100644
--- a/py3.15/multiprocess/resource_tracker.py
+++ b/py3.15/multiprocess/resource_tracker.py
@@ -20,6 +20,7 @@ import os
 import signal
 import sys
 import threading
+import time
 import warnings
 from collections import deque
 
@@ -78,6 +79,10 @@ class ResourceTracker(object):
         # The reader should understand all formats.
         self._use_simple_format = False
 
+        # Set to True by _stop_locked() if the waitpid polling loop ran to
+        # its timeout without reaping the tracker.  Exposed for tests.
+        self._waitpid_timed_out = False
+
     def _reentrant_call_error(self):
         # gh-109629: this happens if an explicit call to the ResourceTracker
         # gets interrupted by a garbage collection, invoking a finalizer (*)
@@ -90,16 +95,51 @@ class ResourceTracker(object):
         # making sure child processess are cleaned before ResourceTracker
         # gets destructed.
         # see https://github.com/python/cpython/issues/88887
-        self._stop(use_blocking_lock=False)
-        
-    def _stop(self, use_blocking_lock=True):
+        # gh-146313: use a timeout to avoid deadlocking if a forked child
+        # still holds the pipe's write end open.
+        self._stop(use_blocking_lock=False, wait_timeout=1.0)
+
+    def _after_fork_in_child(self):
+        # gh-146313: Called in the child right after os.fork().
+        #
+        # The tracker process is a child of the *parent*, not of us, so we
+        # could never waitpid() it anyway.  Clearing _pid means our __del__
+        # becomes a no-op (the early return for _pid is None).
+        #
+        # Whether we keep the inherited _fd depends on who forked us:
+        #
+        #   - multiprocessing.Process with the 'fork' start method sets
+        #     _fork_intent.preserve_fd before forking.  The child keeps the
+        #     fd and reuses the parent's tracker (gh-80849).  This is safe
+        #     because multiprocessing's atexit handler joins all children
+        #     before the parent's __del__ runs, so by then the fd copies
+        #     are gone and the parent can reap the tracker promptly.
+        #
+        #   - A raw os.fork() leaves the flag unset.  We close the fd in the child after forking so
+        #     the parent's __del__ can reap the tracker without waiting
+        #     for the child to exit.  If we later need a tracker, ensure_running()
+        #     will launch a fresh one.
+        self._lock._at_fork_reinit()
+        self._reentrant_messages.clear()
+        self._pid = None
+        self._exitcode = None
+        if (self._fd is not None and
+            not getattr(_fork_intent, 'preserve_fd', False)):
+            fd = self._fd
+            self._fd = None
+            try:
+                os.close(fd)
+            except OSError:
+                pass
+
+    def _stop(self, use_blocking_lock=True, wait_timeout=None):
         if use_blocking_lock:
             with self._lock:
-                self._stop_locked()
+                self._stop_locked(wait_timeout=wait_timeout)
         else:
             acquired = self._lock.acquire(blocking=False)
             try:
-                self._stop_locked()
+                self._stop_locked(wait_timeout=wait_timeout)
             finally:
                 if acquired:
                     self._lock.release()
@@ -109,6 +149,10 @@ class ResourceTracker(object):
         close=os.close,
         waitpid=os.waitpid,
         waitstatus_to_exitcode=os.waitstatus_to_exitcode,
+        monotonic=time.monotonic,
+        sleep=time.sleep,
+        WNOHANG=getattr(os, 'WNOHANG', None),
+        wait_timeout=None,
     ):
         # This shouldn't happen (it might when called by a finalizer)
         # so we check for it anyway.
@@ -125,7 +169,30 @@ class ResourceTracker(object):
         self._fd = None
 
         try:
-            _, status = waitpid(self._pid, 0)
+            if wait_timeout is None:
+                _, status = waitpid(self._pid, 0)
+            else:
+                # gh-146313: A forked child may still hold the pipe's write
+                # end open, preventing the tracker from seeing EOF and
+                # exiting.  Poll with WNOHANG to avoid blocking forever.
+                deadline = monotonic() + wait_timeout
+                delay = 0.001
+                while True:
+                    result_pid, status = waitpid(self._pid, WNOHANG)
+                    if result_pid != 0:
+                        break
+                    remaining = deadline - monotonic()
+                    if remaining <= 0:
+                        # The tracker is still running; it will be
+                        # reparented to PID 1 (or the nearest subreaper)
+                        # when we exit, and reaped there once all pipe
+                        # holders release their fd.
+                        self._pid = None
+                        self._exitcode = None
+                        self._waitpid_timed_out = True
+                        return
+                    delay = min(delay * 2, remaining, 0.1)
+                    sleep(delay)
         except ChildProcessError:
             self._pid = None
             self._exitcode = None
@@ -311,12 +378,24 @@ class ResourceTracker(object):
 
         self._ensure_running_and_write(msg)
 
+# gh-146313: Per-thread flag set by .popen_fork.Popen._launch() just before
+# os.fork(), telling _after_fork_in_child() to keep the inherited pipe fd so
+# the child can reuse this tracker (gh-80849).  Unset for raw os.fork() calls,
+# where the child instead closes the fd so the parent's __del__ can reap the
+# tracker.  Using threading.local() keeps multiple threads calling
+# popen_fork.Popen._launch() at once from clobbering eachothers intent.
+_fork_intent = threading.local()
+
 _resource_tracker = ResourceTracker()
 ensure_running = _resource_tracker.ensure_running
 register = _resource_tracker.register
 unregister = _resource_tracker.unregister
 getfd = _resource_tracker.getfd
 
+# gh-146313: See _after_fork_in_child docstring.
+if hasattr(os, 'register_at_fork'):
+    os.register_at_fork(after_in_child=_resource_tracker._after_fork_in_child)
+
 
 def _decode_message(line):
     if line.startswith(b'{'):
diff --git a/py3.15/multiprocess/tests/__init__.py b/py3.15/multiprocess/tests/__init__.py
index e61949d..fb10e83 100644
--- a/py3.15/multiprocess/tests/__init__.py
+++ b/py3.15/multiprocess/tests/__init__.py
@@ -6334,8 +6334,9 @@ class TestResourceTracker(unittest.TestCase):
     def _is_resource_tracker_reused(conn, pid):
         from multiprocess.resource_tracker import _resource_tracker
         _resource_tracker.ensure_running()
-        # The pid should be None in the child process, expect for the fork
-        # context. It should not be a new value.
+        # The pid should be None in the child (the at-fork handler clears
+        # it for fork; spawn/forkserver children never had it set).  It
+        # should not be a new value.
         reused = _resource_tracker._pid in (None, pid)
         reused &= _resource_tracker._check_alive()
         conn.send(reused)
@@ -6421,6 +6422,188 @@ class TestResourceTracker(unittest.TestCase):
             # restore sigmask to what it was before executing test
             signal.pthread_sigmask(signal.SIG_SETMASK, orig_sigmask)
 
+    @unittest.skipIf(sys.hexversion <= 0x30f00a8, "added in 3.15.0b1")
+    @only_run_in_forkserver_testsuite("avoids redundant testing.")
+    def test_resource_tracker_fork_deadlock(self):
+        # gh-146313: ResourceTracker.__del__ used to deadlock if a forked
+        # child still held the pipe's write end open when the parent
+        # exited, because the parent would block in waitpid() waiting for
+        # the tracker to exit, but the tracker would never see EOF.
+        cmd = '''if 1:
+            import os, signal
+            from multiprocessing.resource_tracker import ensure_running
+            ensure_running()
+            if os.fork() == 0:
+                signal.pause()
+                os._exit(0)
+            # parent falls through and exits, triggering __del__
+        '''
+        proc = subprocess.Popen([sys.executable, '-c', cmd],
+                                start_new_session=True)
+        try:
+            try:
+                proc.wait(timeout=support.SHORT_TIMEOUT)
+            except subprocess.TimeoutExpired:
+                self.fail(
+                    "Parent process deadlocked in ResourceTracker.__del__"
+                )
+            self.assertEqual(proc.returncode, 0)
+        finally:
+            try:
+                os.killpg(proc.pid, signal.SIGKILL)
+            except ProcessLookupError:
+                pass
+            proc.wait()
+
+    @unittest.skipIf(sys.hexversion <= 0x30f00a8, "added in 3.15.0b1")
+    @only_run_in_forkserver_testsuite("avoids redundant testing.")
+    def test_resource_tracker_mp_fork_reuse_and_prompt_reap(self):
+        # gh-146313 / gh-80849: A child started via multiprocessing.Process
+        # with the 'fork' start method should reuse the parent's resource
+        # tracker (the at-fork handler preserves the inherited pipe fd),
+        # *and* the parent should be able to reap the tracker promptly
+        # after joining the child, without hitting the waitpid timeout.
+        cmd = textwrap.dedent('''
+            import multiprocessing as mp
+            from multiprocessing.resource_tracker import _resource_tracker
+
+            def child(conn):
+                # Prove we can talk to the parent's tracker by registering
+                # and unregistering a dummy resource over the inherited fd.
+                # If the fd were closed, ensure_running would launch a new
+                # tracker and _pid would be non-None.
+                _resource_tracker.register("x", "dummy")
+                _resource_tracker.unregister("x", "dummy")
+                conn.send((_resource_tracker._fd is not None,
+                           _resource_tracker._pid is None,
+                           _resource_tracker._check_alive()))
+
+            if __name__ == "__main__":
+                mp.set_start_method("fork")
+                _resource_tracker.ensure_running()
+                r, w = mp.Pipe(duplex=False)
+                p = mp.Process(target=child, args=(w,))
+                p.start()
+                child_has_fd, child_pid_none, child_alive = r.recv()
+                p.join()
+                w.close(); r.close()
+
+                # Now simulate __del__: the child has exited and released
+                # its fd copy, so the tracker should see EOF and exit
+                # promptly -- no timeout.
+                _resource_tracker._stop(wait_timeout=5.0)
+                print(child_has_fd, child_pid_none, child_alive,
+                      _resource_tracker._waitpid_timed_out,
+                      _resource_tracker._exitcode)
+        ''')
+        rc, out, err = script_helper.assert_python_ok('-c', cmd)
+        parts = out.decode().split()
+        self.assertEqual(parts, ['True', 'True', 'True', 'False', '0'],
+            f"unexpected: {parts!r} stderr={err!r}")
+
+    @unittest.skipIf(sys.hexversion <= 0x30f00a8, "added in 3.15.0b1")
+    @only_run_in_forkserver_testsuite("avoids redundant testing.")
+    def test_resource_tracker_raw_fork_prompt_reap(self):
+        # gh-146313: After a raw os.fork() the at-fork handler closes the
+        # child's inherited fd, so the parent can reap the tracker
+        # immediately -- even while the child is still alive -- rather
+        # than waiting out the 1s timeout.
+        cmd = textwrap.dedent('''
+            import os, signal
+            from multiprocessing.resource_tracker import _resource_tracker
+
+            _resource_tracker.ensure_running()
+            r, w = os.pipe()
+            pid = os.fork()
+            if pid == 0:
+                os.close(r)
+                # Report whether our fd was closed by the at-fork handler.
+                os.write(w, b"1" if _resource_tracker._fd is None else b"0")
+                os.close(w)
+                signal.pause()  # stay alive so parent's reap is meaningful
+                os._exit(0)
+            os.close(w)
+            child_fd_closed = os.read(r, 1) == b"1"
+            os.close(r)
+
+            # Child is still alive and paused.  Because it closed its fd
+            # copy, our close below is the last one and the tracker exits.
+            _resource_tracker._stop(wait_timeout=5.0)
+
+            os.kill(pid, signal.SIGKILL)
+            os.waitpid(pid, 0)
+            print(child_fd_closed,
+                  _resource_tracker._waitpid_timed_out,
+                  _resource_tracker._exitcode)
+        ''')
+        rc, out, err = script_helper.assert_python_ok('-c', cmd)
+        parts = out.decode().split()
+        self.assertEqual(parts, ['True', 'False', '0'],
+            f"unexpected: {parts!r} stderr={err!r}")
+
+    @unittest.skipIf(sys.hexversion <= 0x30f00a8, "added in 3.15.0b1")
+    @only_run_in_forkserver_testsuite("avoids redundant testing.")
+    def test_resource_tracker_lock_reinit_after_fork(self):
+        # gh-146313: If a parent thread held the tracker's lock at fork
+        # time, the child would inherit the held lock and deadlock on
+        # its next ensure_running().  The at-fork handler reinits it.
+        cmd = textwrap.dedent('''
+            import os, threading
+            from multiprocessing.resource_tracker import _resource_tracker
+
+            held = threading.Event()
+            release = threading.Event()
+            def hold():
+                with _resource_tracker._lock:
+                    held.set()
+                    release.wait()
+            t = threading.Thread(target=hold)
+            t.start()
+            held.wait()
+
+            pid = os.fork()
+            if pid == 0:
+                ok = _resource_tracker._lock.acquire(timeout=5.0)
+                os._exit(0 if ok else 1)
+
+            release.set()
+            t.join()
+            _, status = os.waitpid(pid, 0)
+            print(os.waitstatus_to_exitcode(status))
+        ''')
+        rc, out, err = script_helper.assert_python_ok(
+            '-W', 'ignore::DeprecationWarning', '-c', cmd)
+        self.assertEqual(out.strip(), b'0',
+            f"child failed to acquire lock: stderr={err!r}")
+
+    @unittest.skipIf(sys.hexversion <= 0x30f00a8, "added in 3.15.0b1")
+    @only_run_in_forkserver_testsuite("avoids redundant testing.")
+    def test_resource_tracker_safety_net_timeout(self):
+        # gh-146313: When an mp.Process(fork) child holds the preserved
+        # fd and the parent calls _stop() without joining (simulating
+        # abnormal shutdown), the safety-net timeout should fire rather
+        # than deadlocking.
+        cmd = textwrap.dedent('''
+            import multiprocessing as mp
+            import signal
+            from multiprocessing.resource_tracker import _resource_tracker
+
+            if __name__ == "__main__":
+                mp.set_start_method("fork")
+                _resource_tracker.ensure_running()
+                p = mp.Process(target=signal.pause)
+                p.start()
+                # Stop WITHOUT joining -- child still holds preserved fd
+                _resource_tracker._stop(wait_timeout=0.5)
+                print(_resource_tracker._waitpid_timed_out)
+                p.terminate()
+                p.join()
+        ''')
+        rc, out, err = script_helper.assert_python_ok('-c', cmd)
+        self.assertEqual(out.strip(), b'True',
+            f"safety-net timeout did not fire: stderr={err!r}")
+
+
 class TestSimpleQueue(unittest.TestCase):
 
     @classmethod
From: Mike McKerns <[email protected]>
Date: Sun, 14 Jun 2026 23:22:37 -0400
Subject: sync with python 3.15.0b2 (#260)

* sync with python 3.15.0b2

* skip ignore_fork context if not available

* fix default for missing warnings_helper

* add skip for versions before behavior change

---
diff --git a/py3.15/Modules/_multiprocess/clinic/posixshmem.c.h b/py3.15/Modules/_multiprocess/clinic/posixshmem.c.h
index a545ff4..a4d7273 100644
--- a/py3.15/Modules/_multiprocess/clinic/posixshmem.c.h
+++ b/py3.15/Modules/_multiprocess/clinic/posixshmem.c.h
@@ -50,9 +50,9 @@ PyDoc_STRVAR(_posixshmem_shm_unlink__doc__,
 "\n"
 "Remove a shared memory object (similar to unlink()).\n"
 "\n"
-"Remove a shared memory object name, and, once all processes  have  unmapped\n"
-"the object, de-allocates and destroys the contents of the associated memory\n"
-"region.");
+"Remove a shared memory object name, and, once all processes have\n"
+"unmapped the object, de-allocates and destroys the contents of the\n"
+"associated memory region.");
 
 #define _POSIXSHMEM_SHM_UNLINK_METHODDEF    \
     {"shm_unlink", (PyCFunction)_posixshmem_shm_unlink, METH_O, _posixshmem_shm_unlink__doc__},
@@ -86,4 +86,4 @@ exit:
 #ifndef _POSIXSHMEM_SHM_UNLINK_METHODDEF
     #define _POSIXSHMEM_SHM_UNLINK_METHODDEF
 #endif /* !defined(_POSIXSHMEM_SHM_UNLINK_METHODDEF) */
-/*[clinic end generated code: output=74588a5abba6e36c input=a9049054013a1b77]*/
+/*[clinic end generated code: output=e69afacce7b0595e input=a9049054013a1b77]*/
diff --git a/py3.15/Modules/_multiprocess/posixshmem.c b/py3.15/Modules/_multiprocess/posixshmem.c
index ab45e41..22b4af2 100644
--- a/py3.15/Modules/_multiprocess/posixshmem.c
+++ b/py3.15/Modules/_multiprocess/posixshmem.c
@@ -81,15 +81,15 @@ _posixshmem.shm_unlink
 
 Remove a shared memory object (similar to unlink()).
 
-Remove a shared memory object name, and, once all processes  have  unmapped
-the object, de-allocates and destroys the contents of the associated memory
-region.
+Remove a shared memory object name, and, once all processes have
+unmapped the object, de-allocates and destroys the contents of the
+associated memory region.
 
 [clinic start generated code]*/
 
 static PyObject *
 _posixshmem_shm_unlink_impl(PyObject *module, PyObject *path)
-/*[clinic end generated code: output=42f8b23d134b9ff5 input=298369d013dcad63]*/
+/*[clinic end generated code: output=42f8b23d134b9ff5 input=cf7a30ec6503cf78]*/
 {
     int rv;
     int async_err = 0;
diff --git a/py3.15/multiprocess/tests/__init__.py b/py3.15/multiprocess/tests/__init__.py
index fb10e83..bc0769c 100644
--- a/py3.15/multiprocess/tests/__init__.py
+++ b/py3.15/multiprocess/tests/__init__.py
@@ -41,6 +41,7 @@ from test.support import threading_helper
 from test.support import warnings_helper
 from test.support import subTests
 from test.support.script_helper import assert_python_failure, assert_python_ok
+warnings_helper_ignore_fork_in_thread_deprecation_warnings = getattr(warnings_helper, 'ignore_fork_in_thread_deprecation_warnings', warnings_helper.check_warnings)
 
 # Skip tests if _multiprocessing wasn't built.
 _multiprocessing = import_helper.import_module('_multiprocessing')
@@ -385,7 +386,7 @@ class _TestProcess(BaseTestCase):
         self.assertEqual(current.ident, os.getpid())
         self.assertEqual(current.exitcode, None)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_set_executable(self):
         if self.TYPE == 'threads':
             self.skipTest(f'test not appropriate for {self.TYPE}')
@@ -402,7 +403,7 @@ class _TestProcess(BaseTestCase):
             p.join()
             self.assertEqual(p.exitcode, 0)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @support.requires_resource('cpu')
     def test_args_argument(self):
         # bpo-45735: Using list or tuple as *args* in constructor could
@@ -450,7 +451,7 @@ class _TestProcess(BaseTestCase):
             q.put(bytes(current.authkey))
             q.put(current.pid)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_parent_process_attributes(self):
         if self.TYPE == "threads":
             self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -471,7 +472,7 @@ class _TestProcess(BaseTestCase):
         from multiprocess.process import parent_process
         wconn.send([parent_process().pid, parent_process().name])
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def _test_parent_process(self):
         if self.TYPE == "threads":
             self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -510,7 +511,7 @@ class _TestProcess(BaseTestCase):
         parent_process().join(timeout=support.SHORT_TIMEOUT)
         wconn.send("alive" if parent_process().is_alive() else "not alive")
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_process(self):
         q = self.Queue(1)
         e = self.Event()
@@ -551,7 +552,7 @@ class _TestProcess(BaseTestCase):
         self.assertNotIn(p, self.active_children())
         close_queue(q)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(threading._HAVE_THREAD_NATIVE_ID, "needs native_id")
     def test_process_mainthread_native_id(self):
         if self.TYPE == 'threads':
@@ -592,7 +593,7 @@ class _TestProcess(BaseTestCase):
     def _test_sleep(cls, delay):
         time.sleep(delay)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def _kill_process(self, meth, target=None):
         if self.TYPE == 'threads':
             self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -650,7 +651,7 @@ class _TestProcess(BaseTestCase):
 
         return p.exitcode
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipIf(os.name == 'nt', "POSIX only")
     def test_interrupt(self):
         exitcode = self._kill_process(multiprocessing.Process.interrupt)
@@ -659,18 +660,18 @@ class _TestProcess(BaseTestCase):
         # (KeyboardInterrupt in this case)
         # in multiprocessing.BaseProcess._bootstrap
         
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipIf(os.name == 'nt', "POSIX only")
     def test_interrupt_no_handler(self):
         exitcode = self._kill_process(multiprocessing.Process.interrupt, target=self._sleep_no_int_handler)
         self.assertEqual(exitcode, -signal.SIGINT)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_terminate(self):
         exitcode = self._kill_process(multiprocessing.Process.terminate)
         self.assertEqual(exitcode, -signal.SIGTERM)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_kill(self):
         exitcode = self._kill_process(multiprocessing.Process.kill)
         if os.name != 'nt':
@@ -686,7 +687,7 @@ class _TestProcess(BaseTestCase):
         self.assertIsInstance(cpus, int)
         self.assertGreaterEqual(cpus, 1)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_active_children(self):
         self.assertEqual(type(self.active_children()), list)
 
@@ -715,7 +716,7 @@ class _TestProcess(BaseTestCase):
                 p.start()
                 p.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipIf(True, "fails with is_dill(obj, child=True)")
     def test_recursion(self):
         rconn, wconn = self.Pipe(duplex=False)
@@ -741,7 +742,7 @@ class _TestProcess(BaseTestCase):
     def _test_sentinel(cls, event):
         event.wait(10.0)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_sentinel(self):
         if self.TYPE == "threads":
             self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -764,7 +765,7 @@ class _TestProcess(BaseTestCase):
             q.get()
         sys.exit(rc)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_close(self):
         if self.TYPE == "threads":
             self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -797,7 +798,7 @@ class _TestProcess(BaseTestCase):
 
         close_queue(q)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @support.requires_resource('walltime')
     def test_many_processes(self):
         if self.TYPE == 'threads':
@@ -835,7 +836,7 @@ class _TestProcess(BaseTestCase):
             for p in procs:
                 self.assertIn(p.exitcode, exitcodes)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_lose_target_ref(self):
         c = DummyCallable()
         wr = weakref.ref(c)
@@ -898,7 +899,7 @@ class _TestProcess(BaseTestCase):
         threading.Thread(target=func1).start()
         threading.Thread(target=func2, daemon=True).start()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_wait_for_threads(self):
         # A child process should wait for non-daemonic threads to end
         # before exiting
@@ -923,7 +924,7 @@ class _TestProcess(BaseTestCase):
             setattr(sys, stream_name, None)
         evt.set()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_error_on_stdio_flush_1(self):
         # Check that Process works with broken standard streams
         streams = [io.StringIO(), None]
@@ -943,7 +944,7 @@ class _TestProcess(BaseTestCase):
                 finally:
                     setattr(sys, stream_name, old_stream)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_error_on_stdio_flush_2(self):
         # Same as test_error_on_stdio_flush_1(), but standard streams are
         # broken by the child process
@@ -1094,7 +1095,7 @@ class _TestSubclassingProcess(BaseTestCase):
 
     ALLOWED_TYPES = ('processes',)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_subclassing(self):
         uppercaser = _UpperCaser()
         uppercaser.daemon = True
@@ -1104,7 +1105,7 @@ class _TestSubclassingProcess(BaseTestCase):
         uppercaser.stop()
         uppercaser.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_stderr_flush(self):
         # sys.stderr is flushed at process shutdown (issue #13812)
         if self.TYPE == "threads":
@@ -1135,7 +1136,7 @@ class _TestSubclassingProcess(BaseTestCase):
         sys.stderr = open(fd, 'w', encoding="utf-8", closefd=False)
         sys.exit(reason)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_sys_exit(self):
         # See Issue 13854
         if self.TYPE == 'threads':
@@ -1203,7 +1204,7 @@ class _TestQueue(BaseTestCase):
             queue.get()
         parent_can_continue.set()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_put(self):
         MAXSIZE = 6
         queue = self.Queue(maxsize=MAXSIZE)
@@ -1273,7 +1274,7 @@ class _TestQueue(BaseTestCase):
         queue.put(5)
         parent_can_continue.set()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_get(self):
         queue = self.Queue()
         child_can_start = self.Event()
@@ -1336,7 +1337,7 @@ class _TestQueue(BaseTestCase):
         # process cannot shutdown until the feeder thread has finished
         # pushing items onto the pipe.
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_fork(self):
         # Old versions of Queue would fail to create a new feeder
         # thread for a forked process if the original process had its
@@ -1387,7 +1388,7 @@ class _TestQueue(BaseTestCase):
             time.sleep(DELTA)
             q.task_done()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_task_done(self):
         queue = self.JoinableQueue()
 
@@ -1431,7 +1432,7 @@ class _TestQueue(BaseTestCase):
                     self.fail("Probable regression on import lock contention;"
                               " see Issue #22853")
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_timeout(self):
         q = multiprocessing.Queue()
         start = time.monotonic()
@@ -1555,7 +1556,7 @@ class _TestLock(BaseTestCase):
         event.set()
         time.sleep(1.0)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_repr_lock(self):
         if self.TYPE != 'processes':
             self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -1619,7 +1620,7 @@ class _TestLock(BaseTestCase):
         res.value = lock.locked()
         event.set()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes')
     def test_lock_locked_2processes(self):
         if self.TYPE != 'processes':
@@ -1646,7 +1647,7 @@ class _TestLock(BaseTestCase):
         for _ in range(n):
             lock.release()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_repr_rlock(self):
         if self.TYPE != 'processes':
             self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -1706,7 +1707,7 @@ class _TestLock(BaseTestCase):
         if sys.hexversion > 0x30e00a6: self.assertFalse(lock.locked())
         self.assertRaises((AssertionError, RuntimeError), lock.release)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes')
     def test_rlock_locked_2processes(self):
         if self.TYPE != 'processes':
@@ -1818,7 +1819,7 @@ class _TestCondition(BaseTestCase):
             except NotImplementedError:
                 pass
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_notify(self):
         cond = self.Condition()
         sleeping = self.Semaphore(0)
@@ -1861,7 +1862,7 @@ class _TestCondition(BaseTestCase):
         threading_helper.join_thread(t)
         join_process(p)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_notify_all(self):
         cond = self.Condition()
         sleeping = self.Semaphore(0)
@@ -1931,7 +1932,7 @@ class _TestCondition(BaseTestCase):
             # NOTE: join_process and join_thread are the same
             threading_helper.join_thread(w)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_notify_n(self):
         cond = self.Condition()
         sleeping = self.Semaphore(0)
@@ -2005,7 +2006,7 @@ class _TestCondition(BaseTestCase):
             if not result or state.value != 4:
                 sys.exit(1)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes')
     def test_waitfor(self):
         # based on test in test/lock_tests.py
@@ -2041,7 +2042,7 @@ class _TestCondition(BaseTestCase):
             if not result and (expected - CLOCK_RES) <= dt:
                 success.value = True
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(HAS_SHAREDCTYPES, 'needs sharedctypes')
     def test_waitfor_timeout(self):
         # based on test in test/lock_tests.py
@@ -2074,7 +2075,7 @@ class _TestCondition(BaseTestCase):
         if pid is not None:
             os.kill(pid, signal.SIGINT)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_wait_result(self):
         if isinstance(self, ProcessesMixin) and sys.platform != 'win32':
             pid = os.getpid()
@@ -2103,7 +2104,7 @@ class _TestEvent(BaseTestCase):
         time.sleep(TIMEOUT2)
         event.set()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_event(self):
         event = self.Event()
         wait = TimingWrapper(event.wait)
@@ -2300,7 +2301,7 @@ class _TestBarrier(BaseTestCase):
             pass
         assert not barrier.broken
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_barrier(self, passes=1):
         """
         Test that a barrier is passed in lockstep
@@ -2308,7 +2309,7 @@ class _TestBarrier(BaseTestCase):
         results = [self.DummyList(), self.DummyList()]
         self.run_threads(self.multipass, (self.barrier, results, passes))
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_barrier_10(self):
         """
         Test that a barrier works for 10 consecutive runs
@@ -2320,7 +2321,7 @@ class _TestBarrier(BaseTestCase):
         res = barrier.wait()
         queue.put(res)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_wait_return(self):
         """
         test the return value from barrier.wait
@@ -2337,7 +2338,7 @@ class _TestBarrier(BaseTestCase):
         if len(results) != 1:
             raise RuntimeError
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_action(self):
         """
         Test the 'action' callback
@@ -2360,7 +2361,7 @@ class _TestBarrier(BaseTestCase):
         except RuntimeError:
             barrier.abort()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_abort(self):
         """
         Test that an abort will put the barrier in a broken state
@@ -2391,7 +2392,7 @@ class _TestBarrier(BaseTestCase):
         barrier.wait()
         results3.append(True)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_reset(self):
         """
         Test that a 'reset' on a barrier frees the waiting threads
@@ -2427,7 +2428,7 @@ class _TestBarrier(BaseTestCase):
         barrier.wait()
         results3.append(True)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_abort_and_reset(self):
         """
         Test that a barrier can be reset after being broken.
@@ -2454,7 +2455,7 @@ class _TestBarrier(BaseTestCase):
         except threading.BrokenBarrierError:
             results.append(True)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_timeout(self):
         """
         Test wait(timeout)
@@ -2474,7 +2475,7 @@ class _TestBarrier(BaseTestCase):
         except threading.BrokenBarrierError:
             results.append(True)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_default_timeout(self):
         """
         Test the barrier's default timeout
@@ -2496,7 +2497,7 @@ class _TestBarrier(BaseTestCase):
             with lock:
                 conn.send(i)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_thousand(self):
         if self.TYPE == 'manager':
             self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -2538,7 +2539,7 @@ class _TestValue(BaseTestCase):
         for sv, cv in zip(values, cls.codes_values):
             sv.value = cv[2]
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_value(self, raw=False):
         if raw:
             values = [self.RawValue(code, value)
@@ -2602,7 +2603,7 @@ class _TestArray(BaseTestCase):
         for i in range(1, len(seq)):
             seq[i] += seq[i-1]
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipIf(c_int is None, "requires _ctypes")
     def test_array(self, raw=False):
         seq = [680, 626, 934, 821, 150, 233, 548, 982, 714, 831]
@@ -2914,7 +2915,7 @@ class _TestPool(BaseTestCase):
 
     @classmethod
     def setUpClass(cls):
-        with warnings_helper.ignore_fork_in_thread_deprecation_warnings():
+        with warnings_helper_ignore_fork_in_thread_deprecation_warnings():
             super().setUpClass()
             cls.pool = cls.Pool(4)
 
@@ -3015,7 +3016,7 @@ class _TestPool(BaseTestCase):
         self.assertEqual(get(), 49)
         self.assertTimingAlmostEqual(get.elapsed, TIMEOUT1)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_async_timeout(self):
         p = self.Pool(3)
         try:
@@ -3113,7 +3114,7 @@ class _TestPool(BaseTestCase):
                 self.assertIn(value, expected_values)
                 expected_values.remove(value)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_make_pool(self):
         expected_error = (RemoteError if self.TYPE == 'manager'
                           else ValueError)
@@ -3129,7 +3130,7 @@ class _TestPool(BaseTestCase):
                 p.close()
                 p.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_terminate(self):
         # Simulate slow tasks which take "forever" to complete
         sleep_time = support.LONG_TIMEOUT
@@ -3147,7 +3148,7 @@ class _TestPool(BaseTestCase):
         p.terminate()
         p.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_empty_iterable(self):
         # See Issue 12157
         p = self.Pool(1)
@@ -3160,7 +3161,7 @@ class _TestPool(BaseTestCase):
         p.close()
         p.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_context(self):
         if self.TYPE == 'processes':
             L = list(range(10))
@@ -3175,7 +3176,7 @@ class _TestPool(BaseTestCase):
     def _test_traceback(cls):
         raise RuntimeError(123) # some comment
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipIf(True, "fails with is_dill(obj, child=True)")
     def test_traceback(self):
         # We want ensure that the traceback from the child process is
@@ -3216,11 +3217,11 @@ class _TestPool(BaseTestCase):
             p.join()
 
     @classmethod
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def _test_wrapped_exception(cls):
         raise RuntimeError('foo')
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipIf(True, "fails with is_dill(obj, child=True)")
     def test_wrapped_exception(self):
         # Issue #20980: Should not wrap exception when using thread pool
@@ -3229,7 +3230,7 @@ class _TestPool(BaseTestCase):
                 p.apply(self._test_wrapped_exception)
         p.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_map_no_failfast(self):
         # Issue #23992: the fail-fast behaviour when an exception is raised
         # during map() would make Pool.join() deadlock, because a worker
@@ -3265,7 +3266,7 @@ class _TestPool(BaseTestCase):
         # they were released too.
         self.assertEqual(CountedObject.n_instances, 0)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_enter(self):
         if self.TYPE == 'manager':
             self.skipTest("test not applicable to manager")
@@ -3282,7 +3283,7 @@ class _TestPool(BaseTestCase):
                 pass
         pool.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_resource_warning(self):
         if self.TYPE == 'manager':
             self.skipTest("test not applicable to manager")
@@ -3308,7 +3309,7 @@ def unpickleable_result():
 class _TestPoolWorkerErrors(BaseTestCase):
     ALLOWED_TYPES = ('processes', )
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_async_error_callback(self):
         p = multiprocessing.Pool(2)
 
@@ -3324,7 +3325,7 @@ class _TestPoolWorkerErrors(BaseTestCase):
         p.close()
         p.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def _test_unpickleable_result(self):
         from multiprocess.pool import MaybeEncodingError
         p = multiprocessing.Pool(2)
@@ -3350,7 +3351,7 @@ class _TestPoolWorkerErrors(BaseTestCase):
 class _TestPoolWorkerLifetime(BaseTestCase):
     ALLOWED_TYPES = ('processes', )
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_pool_worker_lifetime(self):
         p = multiprocessing.Pool(3, maxtasksperchild=10)
         self.assertEqual(3, len(p._pool))
@@ -3380,7 +3381,7 @@ class _TestPoolWorkerLifetime(BaseTestCase):
         p.close()
         p.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_pool_worker_lifetime_early_close(self):
         # Issue #10332: closing a pool whose workers have limited lifetimes
         # before all the tasks completed would make join() hang.
@@ -3454,7 +3455,7 @@ class _TestMyManager(BaseTestCase):
 
     ALLOWED_TYPES = ('manager',)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @support.skip_if_sanitizer('TSan: leaks threads', thread=True)
     def test_mymanager(self):
         manager = MyManager(shutdown_timeout=SHUTDOWN_TIMEOUT)
@@ -3467,7 +3468,7 @@ class _TestMyManager(BaseTestCase):
         # which happens on slow buildbots.
         self.assertIn(manager._process.exitcode, (0, -signal.SIGTERM))
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @support.skip_if_sanitizer('TSan: leaks threads', thread=True)
     def test_mymanager_context(self):
         manager = MyManager(shutdown_timeout=SHUTDOWN_TIMEOUT)
@@ -3478,7 +3479,7 @@ class _TestMyManager(BaseTestCase):
         # which happens on slow buildbots.
         self.assertIn(manager._process.exitcode, (0, -signal.SIGTERM))
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @support.skip_if_sanitizer('TSan: leaks threads', thread=True)
     def test_mymanager_context_prestarted(self):
         manager = MyManager(shutdown_timeout=SHUTDOWN_TIMEOUT)
@@ -3550,7 +3551,7 @@ class _TestRemoteManager(BaseTestCase):
         # Note that xmlrpclib will deserialize object as a list not a tuple
         queue.put(tuple(cls.values))
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @support.skip_if_sanitizer('TSan: leaks threads', thread=True)
     def test_remote(self):
         authkey = os.urandom(32)
@@ -3593,7 +3594,7 @@ class _TestManagerRestart(BaseTestCase):
         queue = manager.get_queue()
         queue.put('hello world')
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @support.skip_if_sanitizer("TSan: leaks threads", thread=True)
     def test_rapid_restart(self):
         authkey = os.urandom(32)
@@ -3647,14 +3648,14 @@ class FakeConnection:
 class TestManagerExceptions(unittest.TestCase):
     # Issue 106558: Manager exceptions avoids creating cyclic references.
     def setUp(self):
-        with warnings_helper.ignore_fork_in_thread_deprecation_warnings():
+        with warnings_helper_ignore_fork_in_thread_deprecation_warnings():
             self.mgr = multiprocessing.Manager()
 
     def tearDown(self):
         self.mgr.shutdown()
         self.mgr.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_queue_get(self):
         queue = self.mgr.Queue()
         if gc.isenabled():
@@ -3666,7 +3667,7 @@ class TestManagerExceptions(unittest.TestCase):
             wr = weakref.ref(e)
         self.assertEqual(wr(), None)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_dispatch(self):
         if gc.isenabled():
             gc.disable()
@@ -3693,7 +3694,7 @@ class _TestConnection(BaseTestCase):
             conn.send_bytes(msg)
         conn.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_connection(self):
         conn, child_conn = self.Pipe()
 
@@ -3786,7 +3787,7 @@ class _TestConnection(BaseTestCase):
             self.assertRaises(OSError, writer.recv)
             self.assertRaises(OSError, writer.poll)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_spawn_close(self):
         # We test that a pipe connection can be closed by parent
         # process immediately after child is spawned.  On Windows this
@@ -3863,7 +3864,7 @@ class _TestConnection(BaseTestCase):
         os.write(fd, data)
         os.close(fd)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction")
     def test_fd_transfer(self):
         if self.TYPE != 'processes':
@@ -3883,7 +3884,7 @@ class _TestConnection(BaseTestCase):
         with open(os_helper.TESTFN, "rb") as f:
             self.assertEqual(f.read(), b"foo")
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction")
     @unittest.skipIf(sys.platform == "win32",
                      "test semantics don't make sense on Windows")
@@ -3921,7 +3922,7 @@ class _TestConnection(BaseTestCase):
     def _send_data_without_fd(self, conn):
         os.write(conn.fileno(), b"\0")
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(HAS_REDUCTION, "test needs multiprocessing.reduction")
     @unittest.skipIf(sys.platform == "win32", "doesn't make sense on Windows")
     def test_missing_fd_transfer(self):
@@ -3953,7 +3954,7 @@ class _TestConnection(BaseTestCase):
             self.assertRaises(OSError, a.recv)
             self.assertRaises(OSError, b.recv)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_wait_empty(self):
         if self.TYPE != 'processes':
             self.skipTest('test not appropriate for {}'.format(self.TYPE))
@@ -4034,7 +4035,7 @@ class _TestListenerClient(BaseTestCase):
         conn.send('hello')
         conn.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_listener_client(self):
         for family in self.connection.families:
             l = self.connection.Listener(family=family)
@@ -4046,7 +4047,7 @@ class _TestListenerClient(BaseTestCase):
             p.join()
             l.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_issue14725(self):
         l = self.connection.Listener()
         p = self.Process(target=self._test, args=(l.address,))
@@ -4092,7 +4093,7 @@ class _TestPoll(BaseTestCase):
             conn.send_bytes(s)
         conn.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_strings(self):
         strings = (b'hello', b'', b'a', b'b', b'', b'bye', b'', b'lop')
         a, b = self.Pipe()
@@ -4116,7 +4117,7 @@ class _TestPoll(BaseTestCase):
         # read from it.
         r.poll(5)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_boundaries(self):
         r, w = self.Pipe(False)
         p = self.Process(target=self._child_boundaries, args=(r,))
@@ -4135,7 +4136,7 @@ class _TestPoll(BaseTestCase):
         b.send_bytes(b'b')
         b.send_bytes(b'cd')
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_dont_merge(self):
         a, b = self.Pipe()
         self.assertEqual(a.poll(0.0), False)
@@ -4204,7 +4205,7 @@ class _TestPicklingConnections(BaseTestCase):
 
         conn.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_pickling(self):
         families = self.connection.families
 
@@ -4263,7 +4264,7 @@ class _TestPicklingConnections(BaseTestCase):
 
         conn.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_access(self):
         # On Windows, if we do not specify a destination pid when
         # using DupHandle then we need to be careful to use the
@@ -4427,7 +4428,7 @@ class _TestSharedCTypes(BaseTestCase):
         for i in range(len(arr)):
             arr[i] *= 2
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_sharedctypes(self, lock=False):
         x = Value('i', 7, lock=lock)
         y = Value(c_double, 1.0/3.0, lock=lock)
@@ -4704,7 +4705,7 @@ class _TestSharedMemory(BaseTestCase):
                 with self.assertRaises(FileNotFoundError):
                     pickle.loads(pickled_sms)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_shared_memory_across_processes(self):
         # bpo-40135: don't define shared memory block's name in case of
         # the failure when we run multiprocessing tests in parallel.
@@ -4733,7 +4734,7 @@ class _TestSharedMemory(BaseTestCase):
 
         sms.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipIf(os.name != "posix", "not feasible in non-posix platforms")
     def test_shared_memory_SharedMemoryServer_ignores_sigint(self):
         # bpo-36368: protect SharedMemoryManager server process from
@@ -4780,7 +4781,7 @@ class _TestSharedMemory(BaseTestCase):
         # properly released sl.
         self.assertFalse(err)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_shared_memory_SharedMemoryManager_basics(self):
         smm1 = multiprocessing.managers.SharedMemoryManager()
         with self.assertRaises(ValueError):
@@ -5122,7 +5123,7 @@ class _TestFinalize(BaseTestCase):
         conn.close()
         os._exit(0)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_finalize(self):
         conn, child_conn = self.Pipe()
 
@@ -5250,7 +5251,7 @@ class _TestLogging(BaseTestCase):
         logger = multiprocessing.get_logger()
         conn.send(logger.getEffectiveLevel())
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_level(self):
         LEVEL1 = 32
         LEVEL2 = 37
@@ -5335,7 +5336,7 @@ class _TestPollEintr(BaseTestCase):
         time.sleep(0.1)
         os.kill(pid, signal.SIGUSR1)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
     def test_poll_eintr(self):
         got_signal = [False]
@@ -5475,7 +5476,7 @@ def initializer(ns):
 @hashlib_helper.requires_hashdigest('sha256')
 class TestInitializers(unittest.TestCase):
     def setUp(self):
-        with warnings_helper.ignore_fork_in_thread_deprecation_warnings():
+        with warnings_helper_ignore_fork_in_thread_deprecation_warnings():
             self.mgr = multiprocessing.Manager()
             self.ns = self.mgr.Namespace()
             self.ns.test = 0
@@ -5484,7 +5485,7 @@ class TestInitializers(unittest.TestCase):
         self.mgr.shutdown()
         self.mgr.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_manager_initializer(self):
         m = multiprocessing.managers.SyncManager()
         self.assertRaises(TypeError, m.start, 1)
@@ -5493,7 +5494,7 @@ class TestInitializers(unittest.TestCase):
         m.shutdown()
         m.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_pool_initializer(self):
         self.assertRaises(TypeError, multiprocessing.Pool, initializer=1)
         p = multiprocessing.Pool(1, initializer, (self.ns,))
@@ -5551,19 +5552,19 @@ class _file_like(object):
 
 class TestStdinBadfiledescriptor(unittest.TestCase):
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_queue_in_process(self):
         proc = multiprocessing.Process(target=_test_process)
         proc.start()
         proc.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_pool_in_process(self):
         p = multiprocessing.Process(target=pool_in_process)
         p.start()
         p.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_flushing(self):
         sio = io.StringIO()
         flike = _file_like(sio)
@@ -5583,7 +5584,7 @@ class TestWait(unittest.TestCase):
             w.send((i, os.getpid()))
         w.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_wait(self, slow=False):
         from multiprocess.connection import wait
         readers = []
@@ -5624,7 +5625,7 @@ class TestWait(unittest.TestCase):
             s.sendall(('%s\n' % i).encode('ascii'))
         s.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_wait_socket(self, slow=False):
         from multiprocess.connection import wait
         l = socket.create_server((socket_helper.HOST, 0))
@@ -5689,7 +5690,7 @@ class TestWait(unittest.TestCase):
         sem.release()
         time.sleep(period)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @support.requires_resource('walltime')
     def test_wait_integer(self):
         from multiprocess.connection import wait
@@ -5734,7 +5735,7 @@ class TestWait(unittest.TestCase):
         p.terminate()
         p.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_neg_timeout(self):
         from multiprocess.connection import wait
         a, b = multiprocessing.Pipe()
@@ -5812,7 +5813,7 @@ class TestTimeouts(unittest.TestCase):
         conn.send(456)
         conn.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_timeout(self):
         old_timeout = socket.getdefaulttimeout()
         try:
@@ -5870,7 +5871,7 @@ class TestForkAwareThreadLock(unittest.TestCase):
             conn.send(len(util._afterfork_registry))
         conn.close()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_lock(self):
         r, w = multiprocessing.Pipe(False)
         l = util.ForkAwareThreadLock()
@@ -5922,7 +5923,7 @@ class TestCloseFds(unittest.TestCase):
             s.close()
             conn.send(None)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_closefd(self):
         if not HAS_REDUCTION:
             raise unittest.SkipTest('requires fd pickling')
@@ -5968,7 +5969,7 @@ class TestIgnoreEINTR(unittest.TestCase):
         conn.send(x)
         conn.send_bytes(b'x' * cls.CONN_MAX_SIZE)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
     def test_ignore(self):
         conn, child_conn = multiprocessing.Pipe()
@@ -6002,7 +6003,7 @@ class TestIgnoreEINTR(unittest.TestCase):
             a = l.accept()
             a.send('welcome')
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
     def test_ignore_listener(self):
         conn, child_conn = multiprocessing.Pipe()
@@ -6037,7 +6038,7 @@ class TestStartMethod(unittest.TestCase):
         p.join()
         self.assertEqual(child_method, ctx.get_start_method())
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_context(self):
         for method in ('fork', 'spawn', 'forkserver'):
             try:
@@ -6054,7 +6055,7 @@ class TestStartMethod(unittest.TestCase):
     def _dummy_func():
         pass
             
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_spawn_dont_set_context(self):
         # Run a process with spawn or forkserver context may change
         # the global start method, see gh-109263.
@@ -6092,7 +6093,7 @@ class TestStartMethod(unittest.TestCase):
         with self.assertRaisesRegex(TypeError, 'module_names must be a list of strings'):
             ctx.set_forkserver_preload([1, 2, 3])
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_set_get(self):
         multiprocessing.set_forkserver_preload(PRELOAD)
         count = 0
@@ -6150,7 +6151,7 @@ class TestStartMethod(unittest.TestCase):
             print(err)
             self.fail("failed spawning forkserver or grandchild")
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipIf(sys.platform == "win32",
                      "Only Spawn on windows so no risk of mixing")
     @only_run_in_spawn_testsuite("avoids redundant testing.")
@@ -6184,7 +6185,7 @@ class TestStartMethod(unittest.TestCase):
         process.start()
         process.join()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_nested_startmethod(self):
         # gh-108520: Regression test to ensure that child process can send its
         # arguments to another process
@@ -6341,7 +6342,7 @@ class TestResourceTracker(unittest.TestCase):
         reused &= _resource_tracker._check_alive()
         conn.send(reused)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_resource_tracker_reused(self):
         from multiprocess.resource_tracker import _resource_tracker
         _resource_tracker.ensure_running()
@@ -6625,7 +6626,7 @@ class TestSimpleQueue(unittest.TestCase):
         with self.assertRaisesRegex(OSError, 'is closed'):
             q.empty()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_empty(self):
         queue = multiprocessing.SimpleQueue()
         child_can_start = multiprocessing.Event()
@@ -6733,7 +6734,7 @@ class TestSyncManagerTypes(unittest.TestCase):
 
     def setUp(self):
         self.manager = self.manager_class()
-        with warnings_helper.ignore_fork_in_thread_deprecation_warnings():
+        with warnings_helper_ignore_fork_in_thread_deprecation_warnings():
             self.manager.start()
         self.proc = None
 
@@ -6783,7 +6784,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         obj.clear()
         obj.wait(0.001)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_event(self):
         o = self.manager.Event()
         o.set()
@@ -6796,7 +6797,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         obj.acquire()
         if sys.hexversion > 0x30e00a6: obj.locked()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_lock(self, lname="Lock"):
         o = getattr(self.manager, lname)()
         self.run_worker(self._test_lock, o)
@@ -6809,7 +6810,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         obj.release()
         if sys.hexversion > 0x30e00a6: obj.locked()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_rlock(self, lname="RLock"):
         o = getattr(self.manager, lname)()
         self.run_worker(self._test_rlock, o)
@@ -6818,7 +6819,7 @@ class TestSyncManagerTypes(unittest.TestCase):
     def _test_semaphore(cls, obj):
         obj.acquire()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_semaphore(self, sname="Semaphore"):
         o = getattr(self.manager, sname)()
         self.run_worker(self._test_semaphore, o)
@@ -6832,7 +6833,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         obj.acquire()
         obj.release()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_condition(self):
         o = self.manager.Condition()
         self.run_worker(self._test_condition, o)
@@ -6842,7 +6843,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         assert obj.parties == 5
         obj.reset()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_barrier(self):
         o = self.manager.Barrier(5)
         self.run_worker(self._test_barrier, o)
@@ -6853,7 +6854,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         with obj:
             pass
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_pool(self):
         o = self.manager.Pool(processes=4)
         self.run_worker(self._test_pool, o)
@@ -6868,7 +6869,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         assert obj.get() == 6
         assert obj.empty()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_queue(self, qname="Queue"):
         o = getattr(self.manager, qname)(2)
         o.put(5)
@@ -6877,7 +6878,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         assert o.empty()
         assert not o.full()
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_joinable_queue(self):
         self.test_queue("JoinableQueue")
 
@@ -6912,7 +6913,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         obj.clear()
         case.assertEqual(len(obj), 0)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_list(self):
         o = self.manager.list()
         o.append(5)
@@ -6954,7 +6955,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         obj.clear()
         case.assertEqual(len(obj), 0)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_dict(self):
         o = self.manager.dict()
         o['foo'] = 5
@@ -6969,7 +6970,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         case.assertEqual(obj.get(), 1)
         obj.set(2)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_value(self):
         o = self.manager.Value('i', 1)
         self.run_worker(self._test_value, o)
@@ -6984,7 +6985,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         case.assertEqual(len(obj), 2)
         case.assertListEqual(list(obj), [0, 1])
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_array(self):
         o = self.manager.Array('i', [0, 1])
         self.run_worker(self._test_array, o)
@@ -6995,7 +6996,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         case.assertEqual(obj.x, 0)
         case.assertEqual(obj.y, 1)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_namespace(self):
         o = self.manager.Namespace()
         o.x = 0
@@ -7115,7 +7116,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         case.assertGreater(obj, {'a'})
         case.assertGreaterEqual(obj, {'a', 'b'})
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_set(self):
         o = self.manager.set()
         self.run_worker(self._test_set_operator_symbols, o)
@@ -7133,7 +7134,7 @@ class TestSyncManagerTypes(unittest.TestCase):
         self.assertSetEqual(o, {"a", "b", "c"})
         self.assertRaises(RemoteError, self.manager.set, 1234)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_set_contain_all_method(self):
         o = self.manager.set()
         set_methods = {
@@ -7188,7 +7189,7 @@ class _TestAtExit(BaseTestCase):
                 f.write("deadbeef")
         atexit.register(exit_handler)
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     def test_atexit(self):
         # gh-83856
         with os_helper.temp_dir() as temp_dir:
@@ -7269,6 +7270,7 @@ class _TestSpawnedSysPath(BaseTestCase):
         self.assertEqual(child_sys_path[1:], sys.path[1:])
         self.assertIsNone(import_error, msg=f"child could not import {self._mod_name}")
 
+    @unittest.skipIf(sys.hexversion <= 0x30f00a2, "added in 3.15.0a3")
     def test_std_streams_flushed_after_preload(self):
         # gh-135335: Check fork server flushes standard streams after
         # preloading modules
@@ -7330,7 +7332,7 @@ class MiscTestCase(unittest.TestCase):
         self.assertEqual("332833500", out.decode('utf-8').strip())
         self.assertFalse(err, msg=err.decode('utf-8'))
 
-    @warnings_helper.ignore_fork_in_thread_deprecation_warnings()
+    @warnings_helper_ignore_fork_in_thread_deprecation_warnings()
     @unittest.skipIf(sys.hexversion <= 0x30e00b1, "added in 3.14.0b2")
     def test_forked_thread_not_started(self):
         # gh-134381: Ensure that a thread that has not been started yet in
@@ -7354,6 +7356,7 @@ class MiscTestCase(unittest.TestCase):
         self.assertEqual(q.get_nowait(), "done")
         close_queue(q)
 
+    @unittest.skipIf(sys.hexversion <= 0x30f00a0, "added in 3.15.0a1")
     def test_preload_main(self):
         # gh-126631: Check that __main__ can be pre-loaded
         if multiprocessing.get_start_method() != "forkserver":
@@ -7484,7 +7487,7 @@ class ManagerMixin(BaseMixin):
 
     @classmethod
     def setUpClass(cls):
-        with warnings_helper.ignore_fork_in_thread_deprecation_warnings():
+        with warnings_helper_ignore_fork_in_thread_deprecation_warnings():
             super().setUpClass()
             cls.manager = multiprocessing.Manager()
 
@@ -7655,6 +7658,7 @@ class SemLockTests(unittest.TestCase):
         _multiprocessing.sem_unlink(name)
 
 
[email protected](sys.hexversion <= 0x30f00a0, "added in 3.15.0a1")
 @unittest.skipIf(sys.platform != "linux", "Linux only")
 class ForkInThreads(unittest.TestCase):
             
@@ -7713,6 +7717,7 @@ class ForkInThreads(unittest.TestCase):
         self.assertIn(b'DeprecationWarning', res.err)
         self.assertIn(b'is multi-threaded, use of forkpty() may lead to deadlocks in the child', res.err)
 
[email protected](sys.hexversion <= 0x30f00a2, "added in 3.15.0a3")
 @unittest.skipUnless(HAS_SHMEM, "requires multiprocessing.shared_memory")
 class TestSharedMemoryNames(unittest.TestCase):
     @subTests('use_simple_format', (True, False))
From: Mike McKerns <[email protected]>
Date: Sat, 18 Jul 2026 14:40:27 -0400
Subject: sync with python 3.15.0b4 (#265)

---
diff --git a/py3.15/multiprocess/managers.py b/py3.15/multiprocess/managers.py
index ec86c41..2ebfc48 100644
--- a/py3.15/multiprocess/managers.py
+++ b/py3.15/multiprocess/managers.py
@@ -1294,9 +1294,9 @@ if HAS_SHMEM:
     class _SharedMemoryTracker:
         "Manages one or more shared memory segments."
 
-        def __init__(self, name, segment_names=[]):
+        def __init__(self, name, segment_names=None):
             self.shared_memory_context_name = name
-            self.segment_names = segment_names
+            self.segment_names = [] if segment_names is None else segment_names
 
         def register_segment(self, segment_name):
             "Adds the supplied shared memory block name to tracker."
From: Mike McKerns <[email protected]>
Date: Sat, 8 Aug 2026 19:59:57 -0400
Subject: sync with 3.14.7 and 3.15.0rc1 (#266)

---
diff --git a/py3.15/multiprocess/tests/test_multiprocessing_forkserver/__init__.py b/py3.15/multiprocess/tests/test_multiprocessing_forkserver/__init__.py
index 90c6de4..6bd4a37 100644
--- a/py3.15/multiprocess/tests/test_multiprocessing_forkserver/__init__.py
+++ b/py3.15/multiprocess/tests/test_multiprocessing_forkserver/__init__.py
@@ -1,3 +1,4 @@
+import multiprocess
 import os.path
 import sys
 import unittest
@@ -18,6 +19,11 @@ if support.PGO:
 if sys.platform == "win32":
     raise unittest.SkipTest("forkserver is not available on Windows")
 
+# The forkserver start method requires passing file descriptors over a Unix
+# socket, which is not available on every platform (e.g. Solaris/illumos).
+if "forkserver" not in multiprocess.get_all_start_methods():
+    raise unittest.SkipTest("forkserver start method is not available")
+
 suite = os.path.dirname(__file__) or os.path.curdir
 tests = glob.glob(suite + os.path.sep + 'test_*.py')
 
From: Mike McKerns <[email protected]>
Date: Fri, 4 Sep 2026 12:36:38 -0400
Subject: sync with 3.15.0rc2 (#269)

---
diff --git a/py3.15/multiprocess/tests/__init__.py b/py3.15/multiprocess/tests/__init__.py
index bc0769c..6c6567f 100644
--- a/py3.15/multiprocess/tests/__init__.py
+++ b/py3.15/multiprocess/tests/__init__.py
@@ -1604,6 +1604,7 @@ class _TestLock(BaseTestCase):
         event.wait()
         self.assertEqual(f'<Lock(owner=SomeOtherProcess)>', repr(lock))
         p.terminate()
+        p.join()
 
     def test_lock(self):
         lock = self.Lock()

Reply via email to