cp -rf py3.10/examples .
cp -rf py3.10/doc .
cp -f py3.10/index.html .
cp -rf py3.10/_multiprocess _multiprocess
cp -rf py3.10/multiprocess multiprocess 
cp -rf py3.10/Modules/_multiprocess Modules/_multiprocess
# ----------------------------------------------------------------------
diff Python-3.10.0rc2/Lib/multiprocessing/connection.py Python-3.11.0a1/Lib/multiprocessing/connection.py
946c946
< # Make connection and socket objects sharable if possible
---
> # Make connection and socket objects shareable if possible
diff Python-3.10.0rc2/Lib/multiprocessing/managers.py Python-3.11.0a1/Lib/multiprocessing/managers.py
1341d1340
<             pass
# ----------------------------------------------------------------------
diff Python-3.10.0rc2/Lib/test/_test_multiprocessing.py Python-3.11.0a1/Lib/test/_test_multiprocessing.py 
613a614
>         gc.collect()  # For PyPy or other GCs.
2669a2671
>         gc.collect()  # For PyPy or other GCs.
3773a3776,3781
>     def _new_shm_name(self, prefix):
>         # Add a PID to the name of a POSIX shared memory object to allow
>         # running multiprocessing tests (test_multiprocessing_fork,
>         # test_multiprocessing_spawn, etc) in parallel.
>         return prefix + str(os.getpid())
> 
3775c3783,3784
<         sms = shared_memory.SharedMemory('test01_tsmb', create=True, size=512)
---
>         name_tsmb = self._new_shm_name('test01_tsmb')
>         sms = shared_memory.SharedMemory(name_tsmb, create=True, size=512)
3779c3788
<         self.assertEqual(sms.name, 'test01_tsmb')
---
>         self.assertEqual(sms.name, name_tsmb)
3787,3793d3795
<         # Test pickling
<         sms.buf[0:6] = b'pickle'
<         pickled_sms = pickle.dumps(sms)
<         sms2 = pickle.loads(pickled_sms)
<         self.assertEqual(sms.name, sms2.name)
<         self.assertEqual(bytes(sms.buf[0:6]), bytes(sms2.buf[0:6]), b'pickle')
< 
3799c3801
<         also_sms = shared_memory.SharedMemory('test01_tsmb')
---
>         also_sms = shared_memory.SharedMemory(name_tsmb)
3804c3806
<         same_sms = shared_memory.SharedMemory('test01_tsmb', size=20*sms.size)
---
>         same_sms = shared_memory.SharedMemory(name_tsmb, size=20*sms.size)
3822c3824
<             names = ['test01_fn', 'test02_fn']
---
>             names = [self._new_shm_name('test01_fn'), self._new_shm_name('test02_fn')]
3843a3846,3851
>             name_dblunlink = self._new_shm_name('test01_dblunlink')
>             sms_uno = shared_memory.SharedMemory(
>                 name_dblunlink,
>                 create=True,
>                 size=5000
>             )
3845,3850d3852
<                 sms_uno = shared_memory.SharedMemory(
<                     'test01_dblunlink',
<                     create=True,
<                     size=5000
<                 )
< 
3854c3856
<                     sms_duo = shared_memory.SharedMemory('test01_dblunlink')
---
>                     sms_duo = shared_memory.SharedMemory(name_dblunlink)
3866c3868
<                 'test01_tsmb',
---
>                 name_tsmb,
3880c3882
<             ok_if_exists_sms = OptionalAttachSharedMemory('test01_tsmb')
---
>             ok_if_exists_sms = OptionalAttachSharedMemory(name_tsmb)
3891a3894,3916
>     def test_shared_memory_recreate(self):
>         # Test if shared memory segment is created properly,
>         # when _make_filename returns an existing shared memory segment name
>         with unittest.mock.patch(
>             'multiprocessing.shared_memory._make_filename') as mock_make_filename:
> 
>             NAME_PREFIX = shared_memory._SHM_NAME_PREFIX
>             names = ['test01_fn', 'test02_fn']
>             # Prepend NAME_PREFIX which can be '/psm_' or 'wnsm_', necessary
>             # because some POSIX compliant systems require name to start with /
>             names = [NAME_PREFIX + name for name in names]
> 
>             mock_make_filename.side_effect = names
>             shm1 = shared_memory.SharedMemory(create=True, size=1)
>             self.addCleanup(shm1.unlink)
>             self.assertEqual(shm1._name, names[0])
> 
>             mock_make_filename.side_effect = names
>             shm2 = shared_memory.SharedMemory(create=True, size=1)
>             self.addCleanup(shm2.unlink)
>             self.assertEqual(shm2._name, names[1])
> 
>     def test_invalid_shared_memory_cration(self):
3903a3929,3969
>     def test_shared_memory_pickle_unpickle(self):
>         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
>             with self.subTest(proto=proto):
>                 sms = shared_memory.SharedMemory(create=True, size=512)
>                 self.addCleanup(sms.unlink)
>                 sms.buf[0:6] = b'pickle'
> 
>                 # Test pickling
>                 pickled_sms = pickle.dumps(sms, protocol=proto)
> 
>                 # Test unpickling
>                 sms2 = pickle.loads(pickled_sms)
>                 self.assertIsInstance(sms2, shared_memory.SharedMemory)
>                 self.assertEqual(sms.name, sms2.name)
>                 self.assertEqual(bytes(sms.buf[0:6]), b'pickle')
>                 self.assertEqual(bytes(sms2.buf[0:6]), b'pickle')
> 
>                 # Test that unpickled version is still the same SharedMemory
>                 sms.buf[0:6] = b'newval'
>                 self.assertEqual(bytes(sms.buf[0:6]), b'newval')
>                 self.assertEqual(bytes(sms2.buf[0:6]), b'newval')
> 
>                 sms2.buf[0:6] = b'oldval'
>                 self.assertEqual(bytes(sms.buf[0:6]), b'oldval')
>                 self.assertEqual(bytes(sms2.buf[0:6]), b'oldval')
> 
>     def test_shared_memory_pickle_unpickle_dead_object(self):
>         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
>             with self.subTest(proto=proto):
>                 sms = shared_memory.SharedMemory(create=True, size=512)
>                 sms.buf[0:6] = b'pickle'
>                 pickled_sms = pickle.dumps(sms, protocol=proto)
> 
>                 # Now, we are going to kill the original object.
>                 # So, unpickled one won't be able to attach to it.
>                 sms.close()
>                 sms.unlink()
> 
>                 with self.assertRaises(FileNotFoundError):
>                     pickle.loads(pickled_sms)
> 
4085c4151,4152
<         sl_copy = shared_memory.ShareableList(sl, name='test03_duplicate')
---
>         name_duplicate = self._new_shm_name('test03_duplicate')
>         sl_copy = shared_memory.ShareableList(sl, name=name_duplicate)
4088c4155
<             self.assertEqual('test03_duplicate', sl_copy.shm.name)
---
>             self.assertEqual(name_duplicate, sl_copy.shm.name)
4120,4139c4187,4222
<         sl = shared_memory.ShareableList(range(10))
<         self.addCleanup(sl.shm.unlink)
< 
<         serialized_sl = pickle.dumps(sl)
<         deserialized_sl = pickle.loads(serialized_sl)
<         self.assertTrue(
<             isinstance(deserialized_sl, shared_memory.ShareableList)
<         )
<         self.assertTrue(deserialized_sl[-1], 9)
<         self.assertFalse(sl is deserialized_sl)
<         deserialized_sl[4] = "changed"
<         self.assertEqual(sl[4], "changed")
< 
<         # Verify data is not being put into the pickled representation.
<         name = 'a' * len(sl.shm.name)
<         larger_sl = shared_memory.ShareableList(range(400))
<         self.addCleanup(larger_sl.shm.unlink)
<         serialized_larger_sl = pickle.dumps(larger_sl)
<         self.assertTrue(len(serialized_sl) == len(serialized_larger_sl))
<         larger_sl.shm.close()
---
>         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
>             with self.subTest(proto=proto):
>                 sl = shared_memory.ShareableList(range(10))
>                 self.addCleanup(sl.shm.unlink)
> 
>                 serialized_sl = pickle.dumps(sl, protocol=proto)
>                 deserialized_sl = pickle.loads(serialized_sl)
>                 self.assertIsInstance(
>                     deserialized_sl, shared_memory.ShareableList)
>                 self.assertEqual(deserialized_sl[-1], 9)
>                 self.assertIsNot(sl, deserialized_sl)
> 
>                 deserialized_sl[4] = "changed"
>                 self.assertEqual(sl[4], "changed")
>                 sl[3] = "newvalue"
>                 self.assertEqual(deserialized_sl[3], "newvalue")
> 
>                 larger_sl = shared_memory.ShareableList(range(400))
>                 self.addCleanup(larger_sl.shm.unlink)
>                 serialized_larger_sl = pickle.dumps(larger_sl, protocol=proto)
>                 self.assertEqual(len(serialized_sl), len(serialized_larger_sl))
>                 larger_sl.shm.close()
> 
>                 deserialized_sl.shm.close()
>                 sl.shm.close()
> 
>     def test_shared_memory_ShareableList_pickling_dead_object(self):
>         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
>             with self.subTest(proto=proto):
>                 sl = shared_memory.ShareableList(range(10))
>                 serialized_sl = pickle.dumps(sl, protocol=proto)
> 
>                 # Now, we are going to kill the original object.
>                 # So, unpickled one won't be able to attach to it.
>                 sl.shm.close()
>                 sl.shm.unlink()
4141,4142c4224,4225
<         deserialized_sl.shm.close()
<         sl.shm.close()
---
>                 with self.assertRaises(FileNotFoundError):
>                     pickle.loads(serialized_sl)
4178a4262,4268
>                 # Without this line it was raising warnings like:
>                 #   UserWarning: resource_tracker:
>                 #   There appear to be 1 leaked shared_memory
>                 #   objects to clean up at shutdown
>                 # See: https://bugs.python.org/issue45209
>                 resource_tracker.unregister(f"/{name}", "shared_memory")
> 
4188c4278
< #
---
> # Test to verify that `Finalize` works.
4199a4290
>         gc.collect()  # For PyPy or other GCs.
4210a4302
>         gc.collect()  # For PyPy or other GCs.
4216a4309
>         gc.collect()  # For PyPy or other GCs.
g
# ----------------------------------------------------------------------
diff Python-3.11.0a1/Lib/test/_test_multiprocessing.py py3.11/multiprocess/tests/__init__.py
3821c3825
<             'multiprocessing.shared_memory._make_filename') as mock_make_filename:
---
>             'multiprocess.shared_memory._make_filename') as mock_make_filename:
3898c3902
<             'multiprocessing.shared_memory._make_filename') as mock_make_filename:
---
>             'multiprocess.shared_memory._make_filename') as mock_make_filename:
# ----------------------------------------------------------------------
diff Python-3.11.0a1/Modules/_multiprocessing/multiprocessing.c Python-3.11.0a3/Modules/_multiprocessing/multiprocessing.c
189,190c189
< #if defined(MS_WINDOWS) ||                                              \
<   (defined(HAVE_SEM_OPEN) && !defined(POSIX_SEMAPHORES_NOT_ENABLED))
---
> #ifdef HAVE_MP_SEMAPHORE
diff Python-3.11.0a1/Modules/_multiprocessing/multiprocessing.h Python-3.11.0a3/Modules/_multiprocessing/multiprocessing.h
23a24
> #  define HAVE_MP_SEMAPHORE
26a28
> #    define HAVE_MP_SEMAPHORE
diff Python-3.11.0a1/Modules/_multiprocessing/semaphore.c Python-3.11.0a3/Modules/_multiprocessing/semaphore.c
11a12,13
> #ifdef HAVE_MP_SEMAPHORE
> 
796a799,800
> 
> #endif // HAVE_MP_SEMAPHORE
# ----------------------------------------------------------------------
cp Python-3.11.0a3/Modules/_multiprocessing/clinic/* py3.11/Modules/_multiprocess/clinic
# ----------------------------------------------------------------------
diff Python-3.11.0a3/Lib/multiprocessing/synchronize.py Python-3.11.0a4/Lib/multiprocessing/synchronize.py
355a356,358
>     def __repr__(self) -> str:
>         set_status = 'set' if self.is_set() else 'unset'
>         return f"<{type(self).__qualname__} at {id(self):#x} {set_status}>"
diff Python-3.11.0a3/Lib/test/_test_multiprocessing.py Python-3.11.0a4/Lib/test/_test_multiprocessing.py 
1648c1648,1661
< #
---
>     def test_repr(self) -> None:
>         event = self.Event()
>         if self.TYPE == 'processes':
>             self.assertRegex(repr(event), r"<Event at .* unset>")
>             event.set()
>             self.assertRegex(repr(event), r"<Event at .* set>")
>             event.clear()
>             self.assertRegex(repr(event), r"<Event at .* unset>")
>         elif self.TYPE == 'manager':
>             self.assertRegex(repr(event), r"<EventProxy object, typeid 'Event' at .*")
>             event.set()
>             self.assertRegex(repr(event), r"<EventProxy object, typeid 'Event' at .*")
> 
> 
# ----------------------------------------------------------------------
diff Python-3.11.0a4/Lib/multiprocessing/managers.py Python-3.11.0a5/Lib/multiprocessing/managers.py
52,56c52,56
< if view_types[0] is not list:       # only needed in Py3.0
<     def rebuild_as_list(obj):
<         return list, (list(obj),)
<     for view_type in view_types:
<         reduction.register(view_type, rebuild_as_list)
---
> def rebuild_as_list(obj):
>     return list, (list(obj),)
> for view_type in view_types:
>     reduction.register(view_type, rebuild_as_list)
> del view_type, view_types
diff Python-3.11.0a4/Lib/multiprocessing/process.py Python-3.11.0a5/Lib/multiprocessing/process.py
429a430
> del name, signum
# ----------------------------------------------------------------------
diff Python-3.11.0a5/Lib/test/_test_multiprocessing.py Python-3.11.0a7/Lib/test/_test_multiprocessing.py 
75a76,81
> if support.check_sanitizer(address=True):
>     # bpo-45200: Skip multiprocessing tests if Python is built with ASAN to
>     # work around a libasan race condition: dead lock in pthread_create().
>     raise unittest.SkipTest("libasan has a pthread_create() dead lock")
> 
> 
249a256,279
>     def test_args_argument(self):
>         # bpo-45735: Using list or tuple as *args* in constructor could
>         # achieve the same effect.
>         args_cases = (1, "str", [1], (1,))
>         args_types = (list, tuple)
> 
>         test_cases = itertools.product(args_cases, args_types)
> 
>         for args, args_type in test_cases:
>             with self.subTest(args=args, args_type=args_type):
>                 q = self.Queue(1)
>                 # pass a tuple or list as args
>                 p = self.Process(target=self._test_args, args=args_type((q, args)))
>                 p.daemon = True
>                 p.start()
>                 child_args = q.get()
>                 self.assertEqual(child_args, args)
>                 p.join()
>                 close_queue(q)
> 
>     @classmethod
>     def _test_args(cls, q, arg):
>         q.put(arg)
> 
# ----------------------------------------------------------------------
diff Python-3.11.0a7/Lib/multiprocessing/connection.py Python-3.11.0b1/Lib/multiprocessing/connection.py
191d190
<         # HACK for byte-indexing of non-bytewise buffers (e.g. array.array)
193,194c192,193
<             m = memoryview(bytes(m))
<         n = len(m)
---
>             m = m.cast('B')
>         n = m.nbytes
Common subdirectories: Python-3.11.0a7/Lib/multiprocessing/dummy and Python-3.11.0b1/Lib/multiprocessing/dummy
diff Python-3.11.0a7/Lib/multiprocessing/managers.py Python-3.11.0b1/Lib/multiprocessing/managers.py
500c500
<                  ctx=None):
---
>                  ctx=None, *, shutdown_timeout=1.0):
509a510
>         self._shutdown_timeout = shutdown_timeout
573,574c574,575
<             args=(self._process, self._address, self._authkey,
<                   self._state, self._Client),
---
>             args=(self._process, self._address, self._authkey, self._state,
>                   self._Client, self._shutdown_timeout),
659c660,661
<     def _finalize_manager(process, address, authkey, state, _Client):
---
>     def _finalize_manager(process, address, authkey, state, _Client,
>                           shutdown_timeout):
674c676
<             process.join(timeout=1.0)
---
>             process.join(timeout=shutdown_timeout)
680c682
<                     process.join(timeout=0.1)
---
>                     process.join(timeout=shutdown_timeout)
682a685,686
>                         process.kill()
>                         process.join()
diff Python-3.11.0a7/Lib/multiprocessing/queues.py Python-3.11.0b1/Lib/multiprocessing/queues.py
142,148c142,145
<         try:
<             self._reader.close()
<         finally:
<             close = self._close
<             if close:
<                 self._close = None
<                 close()
---
>         close = self._close
>         if close:
>             self._close = None
>             close()
172,173c169,171
<                   self._wlock, self._writer.close, self._ignore_epipe,
<                   self._on_queue_feeder_error, self._sem),
---
>                   self._wlock, self._reader.close, self._writer.close,
>                   self._ignore_epipe, self._on_queue_feeder_error,
>                   self._sem),
214,215c212,213
<     def _feed(buffer, notempty, send_bytes, writelock, close, ignore_epipe,
<               onerror, queue_sem):
---
>     def _feed(buffer, notempty, send_bytes, writelock, reader_close,
>               writer_close, ignore_epipe, onerror, queue_sem):
241c239,240
<                             close()
---
>                             reader_close()
>                             writer_close()
diff Python-3.11.0a7/Lib/multiprocessing/spawn.py Python-3.11.0b1/Lib/multiprocessing/spawn.py
36,40d35
< if WINSERVICE:
<     _python_exe = os.path.join(sys.exec_prefix, 'python.exe')
< else:
<     _python_exe = sys.executable
< 
43c38,41
<     _python_exe = exe
---
>     if sys.platform == 'win32':
>         _python_exe = os.fsdecode(exe)
>     else:
>         _python_exe = os.fsencode(exe)
47a46,50
> if WINSERVICE:
>     set_executable(os.path.join(sys.exec_prefix, 'python.exe'))
> else:
>     set_executable(sys.executable)
> 
89c92,93
<         return [_python_exe] + opts + ['-c', prog, '--multiprocessing-fork']
---
>         exe = get_executable()
>         return [exe] + opts + ['-c', prog, '--multiprocessing-fork']
diff Python-3.11.0a7/Lib/multiprocessing/util.py Python-3.11.0b1/Lib/multiprocessing/util.py
123c123
<     raise TypeError('address type of {address!r} unrecognized')
---
>     raise TypeError(f'address type of {address!r} unrecognized')
448a449
>     import subprocess
453c454
<             args, [os.fsencode(path)], True, passfds, None, None,
---
>             args, [path], True, passfds, None, None,
455c456,457
<             False, False, None, None, None, -1, None)
---
>             False, False, -1, None, None, None, -1, None,
>             subprocess._USE_VFORK)
# ----------------------------------------------------------------------
diff Python-3.11.0b1/Lib/multiprocessing/context.py Python-3.11.0b5/Lib/multiprocessing/context.py
225a226,229
>     @staticmethod
>     def _after_fork():
>         return _default_context.get_context().Process._after_fork()
> 
285a290,294
>         @staticmethod
>         def _after_fork():
>             # process is spawned, nothing to do
>             pass
> 
328a338,342
>         @staticmethod
>         def _after_fork():
>             # process is spawned, nothing to do
>             pass
> 
Common subdirectories: Python-3.11.0b1/Lib/multiprocessing/dummy and Python-3.11.0b5/Lib/multiprocessing/dummy
diff Python-3.11.0b1/Lib/multiprocessing/pool.py Python-3.11.0b5/Lib/multiprocessing/pool.py
205a206,208
>         if maxtasksperchild is not None:
>             if not isinstance(maxtasksperchild, int) or maxtasksperchild <= 0:
>                 raise ValueError("maxtasksperchild must be a positive int or None")
diff Python-3.11.0b1/Lib/multiprocessing/process.py Python-3.11.0b5/Lib/multiprocessing/process.py
307,308c307
<                 util._finalizer_registry.clear()
<                 util._run_after_forkers()
---
>                 self._after_fork()
338a338,344
>     @staticmethod
>     def _after_fork():
>         from . import util
>         util._finalizer_registry.clear()
>         util._run_after_forkers()
> 
> 
diff Python-3.11.0b1/Lib/multiprocessing/shared_memory.py Python-3.11.0b5/Lib/multiprocessing/shared_memory.py
25a26
> from . import resource_tracker
119,120c120
<             from .resource_tracker import register
<             register(self._name, "shared_memory")
---
>             resource_tracker.register(self._name, "shared_memory")
240d239
<             from .resource_tracker import unregister
242c241
<             unregister(self._name, "shared_memory")
---
>             resource_tracker.unregister(self._name, "shared_memory")
diff Python-3.11.0b1/Modules/_multiprocessing/semaphore.c Python-3.11.0b5/Modules/_multiprocessing/semaphore.c
457,459c457
<     SemLockObject *self;
< 
<     self = PyObject_New(SemLockObject, type);
---
>     SemLockObject *self = (SemLockObject *)type->tp_alloc(type, 0);
576c574
<     PyObject_Free(self);
---
>     Py_TYPE(self)->tp_free((PyObject*)self);
diff Python-3.11.0b1/Lib/test/_test_multiprocessing.py Python-3.11.0b5/Lib/test/_test_multiprocessing.py 
7a8
> import textwrap
2862a2864,2868
>     def test_pool_maxtasksperchild_invalid(self):
>         for value in [0, -1, 0.5, "12"]:
>             with self.assertRaises(ValueError):
>                 multiprocessing.Pool(3, maxtasksperchild=value)
> 
3968c3974
<             names = ['test01_fn', 'test02_fn']
---
>             names = [self._new_shm_name('test03_fn'), self._new_shm_name('test04_fn')]
5762a5769,5797
> class TestNamedResource(unittest.TestCase):
>     def test_global_named_resource_spawn(self):
>         #
>         # gh-90549: Check that global named resources in main module
>         # will not leak by a subprocess, in spawn context.
>         #
>         testfn = os_helper.TESTFN
>         self.addCleanup(os_helper.unlink, testfn)
>         with open(testfn, 'w', encoding='utf-8') as f:
>             f.write(textwrap.dedent('''\
>                 import multiprocessing as mp
> 
>                 ctx = mp.get_context('spawn')
> 
>                 global_resource = ctx.Semaphore()
> 
>                 def submain(): pass
> 
>                 if __name__ == '__main__':
>                     p = ctx.Process(target=submain)
>                     p.start()
>                     p.join()
>             '''))
>         rc, out, err = test.support.script_helper.assert_python_ok(testfn)
>         # on error, err = 'UserWarning: resource_tracker: There appear to
>         # be 1 leaked semaphore objects to clean up at shutdown'
>         self.assertEqual(err, b'')
> 
> 
5993a6029,6040
> 
> 
> @unittest.skipIf(not hasattr(_multiprocessing, 'SemLock'), 'SemLock not available')
> @unittest.skipIf(sys.platform != "linux", "Linux only")
> class SemLockTests(unittest.TestCase):
> 
>     def test_semlock_subclass(self):
>         class SemLock(_multiprocessing.SemLock):
>             pass
>         name = f'test_semlock_subclass-{os.getpid()}'
>         s = SemLock(1, 0, 10, name, 0)
>         _multiprocessing.sem_unlink(name)
# ----------------------------------------------------------------------
diff Python-3.11.0b5/Lib/multiprocessing/connection.py Python-3.11.0/Lib/multiprocessing/connection.py
76,80d75
<         # Prefer abstract sockets if possible to avoid problems with the address
<         # size.  When coding portable applications, some implementations have
<         # sun_path as short as 92 bytes in the sockaddr_un struct.
<         if util.abstract_sockets_supported:
<             return f"\0listener-{os.getpid()}-{next(_mmap_counter)}"
diff Python-3.11.0b5/Lib/multiprocessing/popen_spawn_win32.py Python-3.11.0/Lib/multiprocessing/popen_spawn_win32.py
57d56
<         cmd = ' '.join('"%s"' % x for x in cmd)
64c63
<             python_exe = sys._base_executable
---
>             cmd[0] = python_exe = sys._base_executable
69a69,70
>         cmd = ' '.join('"%s"' % x for x in cmd)
> 
# ----------------------------------------------------------------------
cp Python-3.11.0/Modules/_multiprocessing/clinic/* Modules/_multiprocess/clinic/
# ----------------------------------------------------------------------
diff Python-3.11.0/Lib/multiprocessing/resource_tracker.py Python-3.11.1/Lib/multiprocessing/resource_tracker.py
164c164
<         if len(name) > 512:
---
>         if len(msg) > 512:
167c167
<             raise ValueError('name too long')
---
>             raise ValueError('msg too long')
diff Python-3.11.0/Lib/multiprocessing/shared_memory.py Python-3.11.1/Lib/multiprocessing/shared_memory.py
176c176,179
<                 size = _winapi.VirtualQuerySize(p_buf)
---
>                 try:
>                     size = _winapi.VirtualQuerySize(p_buf)
>                 finally:
>                     _winapi.UnmapViewOfFile(p_buf)
diff Python-3.11.0/Lib/test/_test_multiprocessing.py Python-3.11.1/Lib/test/_test_multiprocessing.py 
5440a5441,5448
>     def test_too_long_name_resource(self):
>         # gh-96819: Resource names that will make the length of a write to a pipe
>         # greater than PIPE_BUF are not allowed
>         rtype = "shared_memory"
>         too_long_name_resource = "a" * (512 - len(rtype))
>         with self.assertRaises(ValueError):
>             resource_tracker.register(too_long_name_resource, rtype)
> 
6039c6047
<         s = SemLock(1, 0, 10, name, 0)
---
>         s = SemLock(1, 0, 10, name, False)
# ----------------------------------------------------------------------
diff Python-3.11.1/Lib/multiprocessing/process.py Python-3.11.4/Lib/multiprocessing/process.py
64c64
<         if p._popen.poll() is not None:
---
>         if (child_popen := p._popen) and child_popen.poll() is not None:
# ----------------------------------------------------------------------
diff Python-3.11.4/Lib/multiprocessing/forkserver.py Python-3.11.5/Lib/multiprocessing/forkserver.py
64c64
<         if not all(type(mod) is str for mod in self._preload_modules):
---
>         if not all(type(mod) is str for mod in modules_names):
diff Python-3.11.4/Lib/multiprocessing/spawn.py Python-3.11.5/Lib/multiprocessing/spawn.py
34c34
<     WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
---
>     WINSERVICE = sys.executable and sys.executable.lower().endswith("pythonservice.exe")
38c38,40
<     if sys.platform == 'win32':
---
>     if exe is None:
>         _python_exe = exe
>     elif sys.platform == 'win32':
151c153,157
<         is not going to be frozen to produce an executable.''')
---
>         is not going to be frozen to produce an executable.
> 
>         To fix this issue, refer to the "Safe importing of main module"
>         section in https://docs.python.org/3/library/multiprocessing.html
>         ''')
diff Python-3.11.4/Lib/multiprocessing/synchronize.py Python-3.11.5/Lib/multiprocessing/synchronize.py
53,54c53,54
<         name = ctx.get_start_method()
<         unlink_now = sys.platform == 'win32' or name == 'fork'
---
>         self.is_fork_ctx = ctx.get_start_method() == 'fork'
>         unlink_now = sys.platform == 'win32' or self.is_fork_ctx
105a106,110
>             if self.is_fork_ctx:
>                 raise RuntimeError('A SemLock created in a fork context is being '
>                                    'shared with a process in a spawn context. This is '
>                                    'not supported. Please use the same context to create '
>                                    'multiprocessing objects and Process.')
# ----------------------------------------------------------------------
diff Python-3.11.4/Lib/test/_test_multiprocessing.py Python-3.11.5/Lib/test/_test_multiprocessing.py 
15a16
> import functools
33a35
> from test.support import script_helper
172a175,227
> def only_run_in_spawn_testsuite(reason):
>     """Returns a decorator: raises SkipTest when SM != spawn at test time.
> 
>     This can be useful to save overall Python test suite execution time.
>     "spawn" is the universal mode available on all platforms so this limits the
>     decorated test to only execute within test_multiprocessing_spawn.
> 
>     This would not be necessary if we refactored our test suite to split things
>     into other test files when they are not start method specific to be rerun
>     under all start methods.
>     """
> 
>     def decorator(test_item):
> 
>         @functools.wraps(test_item)
>         def spawn_check_wrapper(*args, **kwargs):
>             if (start_method := multiprocessing.get_start_method()) != "spawn":
>                 raise unittest.SkipTest(f"{start_method=}, not 'spawn'; {reason}")
>             return test_item(*args, **kwargs)
> 
>         return spawn_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.")
>     def test_only_run_in_spawn_testsuite(self):
>         if multiprocessing.get_start_method() != "spawn":
>             raise unittest.SkipTest("only run in test_multiprocessing_spawn.")
> 
>         try:
>             @only_run_in_spawn_testsuite("testing this decorator")
>             def return_four_if_spawn():
>                 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("spawn", force=True)
>             self.assertEqual(return_four_if_spawn(), 4)
>             multiprocessing.set_start_method("fork", force=True)
>             with self.assertRaises(unittest.SkipTest) as ctx:
>                 return_four_if_spawn()
>             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)
> 
> 
5240a5296,5303
>     def test_context_check_module_types(self):
>         try:
>             ctx = multiprocessing.get_context('forkserver')
>         except ValueError:
>             raise unittest.SkipTest('forkserver should be available')
>         with self.assertRaisesRegex(TypeError, 'module_names must be a list of strings'):
>             ctx.set_forkserver_preload([1, 2, 3])
> 
5284a5348,5369
>     @unittest.skipIf(sys.platform == "win32",
>                      "Only Spawn on windows so no risk of mixing")
>     @only_run_in_spawn_testsuite("avoids redundant testing.")
>     def test_mixed_startmethod(self):
>         # Fork-based locks cannot be used with spawned process
>         for process_method in ["spawn", "forkserver"]:
>             queue = multiprocessing.get_context("fork").Queue()
>             process_ctx = multiprocessing.get_context(process_method)
>             p = process_ctx.Process(target=close_queue, args=(queue,))
>             err_msg = "A SemLock created in a fork"
>             with self.assertRaisesRegex(RuntimeError, err_msg):
>                 p.start()
> 
>         # non-fork-based locks can be used with all other start methods
>         for queue_method in ["spawn", "forkserver"]:
>             for process_method in multiprocessing.get_all_start_methods():
>                 queue = multiprocessing.get_context(queue_method).Queue()
>                 process_ctx = multiprocessing.get_context(process_method)
>                 p = process_ctx.Process(target=close_queue, args=(queue,))
>                 p.start()
>                 p.join()
> 
5777a5863
>     @only_run_in_spawn_testsuite("spawn specific test.")
5788d5873
< 
5790d5874
< 
5792d5875
< 
5794d5876
< 
5800c5882
<         rc, out, err = test.support.script_helper.assert_python_ok(testfn)
---
>         rc, out, err = script_helper.assert_python_ok(testfn)
5803c5885
<         self.assertEqual(err, b'')
---
>         self.assertFalse(err, msg=err.decode('utf-8'))
5811a5894,5911
>     @only_run_in_spawn_testsuite("avoids redundant testing.")
>     def test_spawn_sys_executable_none_allows_import(self):
>         # Regression test for a bug introduced in
>         # https://github.com/python/cpython/issues/90876 that caused an
>         # ImportError in multiprocessing when sys.executable was None.
>         # This can be true in embedded environments.
>         rc, out, err = script_helper.assert_python_ok(
>             "-c",
>             """if 1:
>             import sys
>             sys.executable = None
>             assert "multiprocessing" not in sys.modules, "already imported!"
>             import multiprocessing
>             import multiprocessing.spawn  # This should not fail\n""",
>         )
>         self.assertEqual(rc, 0)
>         self.assertFalse(err, msg=err.decode('utf-8'))
> 
# ----------------------------------------------------------------------
diff Python-3.11.5/Modules/_multiprocessing/semaphore.c Python-3.11.6/Modules/_multiprocessing/semaphore.c
519,521d518
<     if (handle != SEM_FAILED)
<         SEM_CLOSE(handle);
<     PyMem_Free(name_copy);
524a522,524
>     if (handle != SEM_FAILED)
>         SEM_CLOSE(handle);
>     PyMem_Free(name_copy);
558a559
>             PyErr_SetFromErrno(PyExc_OSError);
560c561
<             return PyErr_SetFromErrno(PyExc_OSError);
---
>             return NULL;
diff Python-3.11.5/Lib/multiprocessing/connection.py Python-3.11.6/Lib/multiprocessing/connection.py
11a12
> import errno
273a275
>         _send_ov = None
275a278,281
>             ov = self._send_ov
>             if ov is not None:
>                 # Interrupt WaitForMultipleObjects() in _send_bytes()
>                 ov.cancel()
278a285,288
>             if self._send_ov is not None:
>                 # A connection should only be used by a single thread
>                 raise ValueError("concurrent send_bytes() calls "
>                                  "are not supported")
279a290
>             self._send_ov = ov
288a300
>                 self._send_ov = None
289a302,306
>             if err == _winapi.ERROR_OPERATION_ABORTED:
>                 # close() was called by another thread while
>                 # WaitForMultipleObjects() was waiting for the overlapped
>                 # operation.
>                 raise OSError(errno.EPIPE, "handle is closed")
diff Python-3.11.5/Lib/multiprocessing/popen_spawn_win32.py Python-3.11.6/Lib/multiprocessing/popen_spawn_win32.py
16a17
> # Exit code used by Popen.terminate()
125,126c126,130
<             except OSError:
<                 if self.wait(timeout=1.0) is None:
---
>             except PermissionError:
>                 # ERROR_ACCESS_DENIED (winerror 5) is received when the
>                 # process already died.
>                 code = _winapi.GetExitCodeProcess(int(self._handle))
>                 if code == _winapi.STILL_ACTIVE:
127a132,134
>                 self.returncode = code
>             else:
>                 self.returncode = -signal.SIGTERM
diff Python-3.11.5/Lib/multiprocessing/resource_tracker.py Python-3.11.6/Lib/multiprocessing/resource_tracker.py
53a54,57
> class ReentrantCallError(RuntimeError):
>     pass
> 
> 
57c61
<         self._lock = threading.Lock()
---
>         self._lock = threading.RLock()
60a65,72
>     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 (*)
>         # that itself calls back into ResourceTracker.
>         #   (*) for example the SemLock finalizer
>         raise ReentrantCallError(
>             "Reentrant call into the multiprocessing resource tracker")
> 
62a75,78
>             # This should not happen (_stop() isn't called by a finalizer)
>             # but we check for it anyway.
>             if self._lock._recursion_count() > 1:
>                 return self._reentrant_call_error()
83a100,102
>             if self._lock._recursion_count() > 1:
>                 # The code below is certainly not reentrant-safe, so bail out
>                 return self._reentrant_call_error()
162c181,191
<         self.ensure_running()
---
>         try:
>             self.ensure_running()
>         except ReentrantCallError:
>             # The code below might or might not work, depending on whether
>             # the resource tracker was already running and still alive.
>             # Better warn the user.
>             # (XXX is warnings.warn itself reentrant-safe? :-)
>             warnings.warn(
>                 f"ResourceTracker called reentrantly for resource cleanup, "
>                 f"which is unsupported. "
>                 f"The {rtype} object {name!r} might leak.")
178a208
> 
diff Python-3.11.5/Lib/multiprocessing/synchronize.py Python-3.11.6/Lib/multiprocessing/synchronize.py
53,54c53,54
<         self.is_fork_ctx = ctx.get_start_method() == 'fork'
<         unlink_now = sys.platform == 'win32' or self.is_fork_ctx
---
>         self._is_fork_ctx = ctx.get_start_method() == 'fork'
>         unlink_now = sys.platform == 'win32' or self._is_fork_ctx
106c106
<             if self.is_fork_ctx:
---
>             if self._is_fork_ctx:
117a118,119
>         # Ensure that deserialized SemLock can be serialized again (gh-108520).
>         self._is_fork_ctx = False
diff Python-3.11.5/Lib/test/_test_multiprocessing.py Python-3.11.6/Lib/test/_test_multiprocessing.py 
81c81
<     # bpo-45200: Skip multiprocessing tests if Python is built with ASAN to
---
>     # gh-89363: Skip multiprocessing tests if Python is built with ASAN to
330a331
>     @support.requires_resource('cpu')
558,559c559
<         if os.name != 'nt':
<             self.assertEqual(exitcode, -signal.SIGTERM)
---
>         self.assertEqual(exitcode, -signal.SIGTERM)
564a565,566
>         else:
>             self.assertEqual(exitcode, -signal.SIGTERM)
675a678
>     @support.requires_resource('walltime')
4472a4476
>     @support.requires_resource('cpu')
4919a4924
>     @support.requires_resource('walltime')
4947a4953
>     @support.requires_resource('walltime')
5369a5376,5403
>     @classmethod
>     def _put_one_in_queue(cls, queue):
>         queue.put(1)
> 
>     @classmethod
>     def _put_two_and_nest_once(cls, queue):
>         queue.put(2)
>         process = multiprocessing.Process(target=cls._put_one_in_queue, args=(queue,))
>         process.start()
>         process.join()
> 
>     def test_nested_startmethod(self):
>         # gh-108520: Regression test to ensure that child process can send its
>         # arguments to another process
>         queue = multiprocessing.Queue()
> 
>         process = multiprocessing.Process(target=self._put_two_and_nest_once, args=(queue,))
>         process.start()
>         process.join()
> 
>         results = []
>         while not queue.empty():
>             results.append(queue.get())
> 
>         # gh-109706: queue.put(1) can write into the queue before queue.put(2),
>         # there is no synchronization in the test.
>         self.assertSetEqual(set(results), set([2, 1]))
> 
6052c6086,6087
< def install_tests_in_module_dict(remote_globs, start_method):
---
> def install_tests_in_module_dict(remote_globs, start_method,
>                                  only_type=None, exclude_types=False):
6064a6100,6103
>                 if only_type and type_ != only_type:
>                     continue
>                 if exclude_types:
>                     continue
6074a6114,6116
>             if only_type:
>                 continue
> 
# ----------------------------------------------------------------------
diff Python-3.11.6/Lib/test/_test_multiprocessing.py Python-3.11.7/Lib/test/_test_multiprocessing.py 
80c80
< if support.check_sanitizer(address=True):
---
> if support.HAVE_ASAN_FORK_BUG:
83c83,88
<     raise unittest.SkipTest("libasan has a pthread_create() dead lock")
---
>     raise unittest.SkipTest("libasan has a pthread_create() dead lock related to thread+fork")
> 
> 
> # gh-110666: Tolerate a difference of 100 ms when comparing timings
> # (clock resolution)
> CLOCK_RES = 0.100
1653c1658
<             expected = 0.1
---
>             expected = 0.100
1657,1658c1662
<             # borrow logic in assertTimeout() from test/lock_tests.py
<             if not result and expected * 0.6 < dt < expected * 10.0:
---
>             if not result and (expected - CLOCK_RES) <= dt:
1677c1681
<             time.sleep(0.01)
---
>             time.sleep(0.010)
2436,2437c2440,2444
< def sqr(x, wait=0.0):
<     time.sleep(wait)
---
> def sqr(x, wait=0.0, event=None):
>     if event is None:
>         time.sleep(wait)
>     else:
>         event.wait(wait)
2576,2579c2583,2594
<         res = self.pool.apply_async(sqr, (6, TIMEOUT2 + 1.0))
<         get = TimingWrapper(res.get)
<         self.assertRaises(multiprocessing.TimeoutError, get, timeout=TIMEOUT2)
<         self.assertTimingAlmostEqual(get.elapsed, TIMEOUT2)
---
>         p = self.Pool(3)
>         try:
>             event = threading.Event() if self.TYPE == 'threads' else None
>             res = p.apply_async(sqr, (6, TIMEOUT2 + support.SHORT_TIMEOUT, event))
>             get = TimingWrapper(res.get)
>             self.assertRaises(multiprocessing.TimeoutError, get, timeout=TIMEOUT2)
>             self.assertTimingAlmostEqual(get.elapsed, TIMEOUT2)
>         finally:
>             if event is not None:
>                 event.set()
>             p.terminate()
>             p.join()
2680,2687c2695,2700
<         result = self.pool.map_async(
<             time.sleep, [0.1 for i in range(10000)], chunksize=1
<             )
<         self.pool.terminate()
<         join = TimingWrapper(self.pool.join)
<         join()
<         # Sanity check the pool didn't wait for all tasks to finish
<         self.assertLess(join.elapsed, 2.0)
---
>         # Simulate slow tasks which take "forever" to complete
>         p = self.Pool(3)
>         args = [support.LONG_TIMEOUT for i in range(10_000)]
>         result = p.map_async(time.sleep, args, chunksize=1)
>         p.terminate()
>         p.join()
4379,4383c4392,4394
<             deadline = time.monotonic() + support.LONG_TIMEOUT
<             t = 0.1
<             while time.monotonic() < deadline:
<                 time.sleep(t)
<                 t = min(t*2, 5)
---
>             err_msg = ("A SharedMemory segment was leaked after "
>                        "a process was abruptly terminated")
>             for _ in support.sleeping_retry(support.LONG_TIMEOUT, err_msg):
4388,4390d4398
<             else:
<                 raise AssertionError("A SharedMemory segment was leaked after"
<                                      " a process was abruptly terminated.")
4839c4847
<                 time.sleep(random.random()*0.1)
---
>                 time.sleep(random.random() * 0.100)
4879c4887
<                 time.sleep(random.random()*0.1)
---
>                 time.sleep(random.random() * 0.100)
4928c4936
<         expected = 5
---
>         timeout = 5.0  # seconds
4932c4940
<         res = wait([a, b], expected)
---
>         res = wait([a, b], timeout)
4936,4937c4944
<         self.assertLess(delta, expected * 2)
<         self.assertGreater(delta, expected * 0.5)
---
>         self.assertGreater(delta, timeout - CLOCK_RES)
4940,4941d4946
< 
<         start = time.monotonic()
4943,4944d4947
<         delta = time.monotonic() - start
< 
4946d4948
<         self.assertLess(delta, 0.4)
5461,5463c5463,5466
<                 deadline = time.monotonic() + support.LONG_TIMEOUT
<                 while time.monotonic() < deadline:
<                     time.sleep(.5)
---
>                 err_msg = (f"A {rtype} resource was leaked after a process was "
>                            f"abruptly terminated")
>                 for _ in support.sleeping_retry(support.SHORT_TIMEOUT,
>                                                   err_msg):
5471,5474c5474
<                 else:
<                     raise AssertionError(
<                         f"A {rtype} resource was leaked after a process was "
<                         f"abruptly terminated.")
---
> 
5709a5710
> 
5711,5720c5712,5713
<         t = 0.01
<         while len(multiprocessing.active_children()) > 1:
<             time.sleep(t)
<             t *= 2
<             dt = time.monotonic() - start_time
<             if dt >= 5.0:
<                 test.support.environment_altered = True
<                 support.print_warning(f"multiprocessing.Manager still has "
<                                       f"{multiprocessing.active_children()} "
<                                       f"active children after {dt} seconds")
---
>         for _ in support.sleeping_retry(5.0, error=False):
>             if len(multiprocessing.active_children()) <= 1:
5721a5715,5720
>         else:
>             dt = time.monotonic() - start_time
>             support.environment_altered = True
>             support.print_warning(f"multiprocessing.Manager still has "
>                                   f"{multiprocessing.active_children()} "
>                                   f"active children after {dt:.1f} seconds")
6034,6043c6033,6034
<         t = 0.01
<         while len(multiprocessing.active_children()) > 1:
<             time.sleep(t)
<             t *= 2
<             dt = time.monotonic() - start_time
<             if dt >= 5.0:
<                 test.support.environment_altered = True
<                 support.print_warning(f"multiprocessing.Manager still has "
<                                       f"{multiprocessing.active_children()} "
<                                       f"active children after {dt} seconds")
---
>         for _ in support.sleeping_retry(5.0, error=False):
>             if len(multiprocessing.active_children()) <= 1:
6044a6036,6041
>         else:
>             dt = time.monotonic() - start_time
>             support.environment_altered = True
>             support.print_warning(f"multiprocessing.Manager still has "
>                                   f"{multiprocessing.active_children()} "
>                                   f"active children after {dt:.1f} seconds")
# ----------------------------------------------------------------------
diff Python-3.11.7/Lib/multiprocessing/managers.py Python-3.11.8/Lib/multiprocessing/managers.py
156c156
<         self.listener = Listener(address=address, backlog=16)
---
>         self.listener = Listener(address=address, backlog=128)
diff Python-3.11.7/Lib/multiprocessing/popen_spawn_win32.py Python-3.11.8/Lib/multiprocessing/popen_spawn_win32.py
104,115c104,117
<         if self.returncode is None:
<             if timeout is None:
<                 msecs = _winapi.INFINITE
<             else:
<                 msecs = max(0, int(timeout * 1000 + 0.5))
< 
<             res = _winapi.WaitForSingleObject(int(self._handle), msecs)
<             if res == _winapi.WAIT_OBJECT_0:
<                 code = _winapi.GetExitCodeProcess(self._handle)
<                 if code == TERMINATE:
<                     code = -signal.SIGTERM
<                 self.returncode = code
---
>         if self.returncode is not None:
>             return self.returncode
> 
>         if timeout is None:
>             msecs = _winapi.INFINITE
>         else:
>             msecs = max(0, int(timeout * 1000 + 0.5))
> 
>         res = _winapi.WaitForSingleObject(int(self._handle), msecs)
>         if res == _winapi.WAIT_OBJECT_0:
>             code = _winapi.GetExitCodeProcess(self._handle)
>             if code == TERMINATE:
>                 code = -signal.SIGTERM
>             self.returncode = code
123,134c125,140
<         if self.returncode is None:
<             try:
<                 _winapi.TerminateProcess(int(self._handle), TERMINATE)
<             except PermissionError:
<                 # ERROR_ACCESS_DENIED (winerror 5) is received when the
<                 # process already died.
<                 code = _winapi.GetExitCodeProcess(int(self._handle))
<                 if code == _winapi.STILL_ACTIVE:
<                     raise
<                 self.returncode = code
<             else:
<                 self.returncode = -signal.SIGTERM
---
>         if self.returncode is not None:
>             return
> 
>         try:
>             _winapi.TerminateProcess(int(self._handle), TERMINATE)
>         except PermissionError:
>             # ERROR_ACCESS_DENIED (winerror 5) is received when the
>             # process already died.
>             code = _winapi.GetExitCodeProcess(int(self._handle))
>             if code == _winapi.STILL_ACTIVE:
>                 raise
> 
>         # gh-113009: Don't set self.returncode. Even if GetExitCodeProcess()
>         # returns an exit code different than STILL_ACTIVE, the process can
>         # still be running. Only set self.returncode once WaitForSingleObject()
>         # returns WAIT_OBJECT_0 in wait().
diff Python-3.11.7/Lib/multiprocessing/resource_sharer.py Python-3.11.8/Lib/multiprocessing/resource_sharer.py
126c126
<         self._listener = Listener(authkey=process.current_process().authkey)
---
>         self._listener = Listener(authkey=process.current_process().authkey, backlog=128)
diff Python-3.11.7/Lib/multiprocessing/util.py Python-3.11.8/Lib/multiprocessing/util.py
46c46
<         _logger.log(SUBDEBUG, msg, *args)
---
>         _logger.log(SUBDEBUG, msg, *args, stacklevel=2)
50c50
<         _logger.log(DEBUG, msg, *args)
---
>         _logger.log(DEBUG, msg, *args, stacklevel=2)
54c54
<         _logger.log(INFO, msg, *args)
---
>         _logger.log(INFO, msg, *args, stacklevel=2)
58c58
<         _logger.log(SUBWARNING, msg, *args)
---
>         _logger.log(SUBWARNING, msg, *args, stacklevel=2)
133c133,136
<     rmtree(tempdir)
---
>     def onerror(func, path, err_info):
>         if not issubclass(err_info[0], FileNotFoundError):
>             raise
>     rmtree(tempdir, onerror=onerror)
diff Python-3.11.7/Lib/test/_test_multiprocessing.py Python-3.11.8/Lib/test/_test_multiprocessing.py 
2695a2696,2703
>         sleep_time = support.LONG_TIMEOUT
> 
>         if self.TYPE == 'threads':
>             # Thread pool workers can't be forced to quit, so if the first
>             # task starts early enough, we will end up waiting for it.
>             # Sleep for a shorter time, so the test doesn't block.
>             sleep_time = 1
> 
2697c2705
<         args = [support.LONG_TIMEOUT for i in range(10_000)]
---
>         args = [sleep_time for i in range(10_000)]
2698a2707
>         time.sleep(0.2)  # give some tasks a chance to start
4631a4641,4663
>     def test_filename(self):
>         logger = multiprocessing.get_logger()
>         original_level = logger.level
>         try:
>             logger.setLevel(util.DEBUG)
>             stream = io.StringIO()
>             handler = logging.StreamHandler(stream)
>             logging_format = '[%(levelname)s] [%(filename)s] %(message)s'
>             handler.setFormatter(logging.Formatter(logging_format))
>             logger.addHandler(handler)
>             logger.info('1')
>             util.info('2')
>             logger.debug('3')
>             filename = os.path.basename(__file__)
>             log_record = stream.getvalue()
>             self.assertIn(f'[INFO] [{filename}] 1', log_record)
>             self.assertIn(f'[INFO] [{filename}] 2', log_record)
>             self.assertIn(f'[DEBUG] [{filename}] 3', log_record)
>         finally:
>             logger.setLevel(original_level)
>             logger.removeHandler(handler)
>             handler.close()
> 
# ----------------------------------------------------------------------
diff Python-3.11.8/Modules/_multiprocessing/posixshmem.c Python-3.11.9/Modules/_multiprocessing/posixshmem.c
45c45,46
<     const char *name = PyUnicode_AsUTF8(path);
---
>     Py_ssize_t name_size;
>     const char *name = PyUnicode_AsUTF8AndSize(path, &name_size);
48a50,53
>     if (strlen(name) != (size_t)name_size) {
>         PyErr_SetString(PyExc_ValueError, "embedded null character");
>         return -1;
>     }
84c89,90
<     const char *name = PyUnicode_AsUTF8(path);
---
>     Py_ssize_t name_size;
>     const char *name = PyUnicode_AsUTF8AndSize(path, &name_size);
87a94,97
>     if (strlen(name) != (size_t)name_size) {
>         PyErr_SetString(PyExc_ValueError, "embedded null character");
>         return NULL;
>     }
diff Python-3.11.8/Lib/multiprocessing/connection.py Python-3.11.9/Lib/multiprocessing/connection.py
478a479
> 
480c481
<         if self._authkey:
---
>         if self._authkey is not None:
diff Python-3.11.8/Lib/test/_test_multiprocessing.py Python-3.11.9/Lib/test/_test_multiprocessing.py 
3467a3468,3491
>     def test_empty_authkey(self):
>         # bpo-43952: allow empty bytes as authkey
>         def handler(*args):
>             raise RuntimeError('Connection took too long...')
> 
>         def run(addr, authkey):
>             client = self.connection.Client(addr, authkey=authkey)
>             client.send(1729)
> 
>         key = b''
> 
>         with self.connection.Listener(authkey=key) as listener:
>             thread = threading.Thread(target=run, args=(listener.address, key))
>             thread.start()
>             try:
>                 with listener.accept() as d:
>                     self.assertEqual(d.recv(), 1729)
>             finally:
>                 thread.join()
> 
>         if self.TYPE == 'processes':
>             with self.assertRaises(OSError):
>                 listener.accept()
> 
3934a3959,3973
>     def test_shared_memory_name_with_embedded_null(self):
>         name_tsmb = self._new_shm_name('test01_null')
>         sms = shared_memory.SharedMemory(name_tsmb, create=True, size=512)
>         self.addCleanup(sms.unlink)
>         with self.assertRaises(ValueError):
>             shared_memory.SharedMemory(name_tsmb + '\0a', create=False, size=512)
>         if shared_memory._USE_POSIX:
>             orig_name = sms._name
>             try:
>                 sms._name = orig_name + '\0a'
>                 with self.assertRaises(ValueError):
>                     sms.unlink()
>             finally:
>                 sms._name = orig_name
> 
4069c4108
<     def test_invalid_shared_memory_cration(self):
---
>     def test_invalid_shared_memory_creation(self):
