cp -rf py3.12/examples .
cp -rf py3.12/doc .
cp -f py3.12/index.html .
cp -rf py3.12/_multiprocess _multiprocess
cp -rf Python-3.13.0a1/Modules/_multiprocessing Modules/_multiprocess
cp -rf py3.12/multiprocess multiprocess
# ----------------------------------------------------------------------
diff /Users/mmckerns/src/Python-3.13.0a1/Modules/_multiprocessing/semaphore.c Modules/_multiprocess/semaphore.c
10c10
< #include "multiprocessing.h"
---
> #include "multiprocess.h"
39,40c39,40
< module _multiprocessing
< class _multiprocessing.SemLock "SemLockObject *" "&_PyMp_SemLockType"
---
> module _multiprocess
> class _multiprocess.SemLock "SemLockObject *" "&_PyMp_SemLockType"
84c84
< _multiprocessing.SemLock.acquire
---
> _multiprocess.SemLock.acquire
93c93
< _multiprocessing_SemLock_acquire_impl(SemLockObject *self, int blocking,
---
> _multiprocess_SemLock_acquire_impl(SemLockObject *self, int blocking,
175c175
< _multiprocessing.SemLock.release
---
> _multiprocess.SemLock.release
181c181
< _multiprocessing_SemLock_release_impl(SemLockObject *self)
---
> _multiprocess_SemLock_release_impl(SemLockObject *self)
300c300
< _multiprocessing.SemLock.acquire
---
> _multiprocess.SemLock.acquire
309c309
< _multiprocessing_SemLock_acquire_impl(SemLockObject *self, int blocking,
---
> _multiprocess_SemLock_acquire_impl(SemLockObject *self, int blocking,
385c385
< _multiprocessing.SemLock.release
---
> _multiprocess.SemLock.release
391c391
< _multiprocessing_SemLock_release_impl(SemLockObject *self)
---
> _multiprocess_SemLock_release_impl(SemLockObject *self)
475c475
< _multiprocessing.SemLock.__new__
---
> _multiprocess.SemLock.__new__
486c486
< _multiprocessing_SemLock_impl(PyTypeObject *type, int kind, int value,
---
> _multiprocess_SemLock_impl(PyTypeObject *type, int kind, int value,
534c534
< _multiprocessing.SemLock._rebuild
---
> _multiprocess.SemLock._rebuild
545c545
< _multiprocessing_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle,
---
> _multiprocess_SemLock__rebuild_impl(PyTypeObject *type, SEM_HANDLE handle,
586c586
< _multiprocessing.SemLock._count
---
> _multiprocess.SemLock._count
592c592
< _multiprocessing_SemLock__count_impl(SemLockObject *self)
---
> _multiprocess_SemLock__count_impl(SemLockObject *self)
599c599
< _multiprocessing.SemLock._is_mine
---
> _multiprocess.SemLock._is_mine
605c605
< _multiprocessing_SemLock__is_mine_impl(SemLockObject *self)
---
> _multiprocess_SemLock__is_mine_impl(SemLockObject *self)
613c613
< _multiprocessing.SemLock._get_value
---
> _multiprocess.SemLock._get_value
619c619
< _multiprocessing_SemLock__get_value_impl(SemLockObject *self)
---
> _multiprocess_SemLock__get_value_impl(SemLockObject *self)
638c638
< _multiprocessing.SemLock._is_zero
---
> _multiprocess.SemLock._is_zero
644c644
< _multiprocessing_SemLock__is_zero_impl(SemLockObject *self)
---
> _multiprocess_SemLock__is_zero_impl(SemLockObject *self)
666c666
< _multiprocessing.SemLock._after_fork
---
> _multiprocess.SemLock._after_fork
672c672
< _multiprocessing_SemLock__after_fork_impl(SemLockObject *self)
---
> _multiprocess_SemLock__after_fork_impl(SemLockObject *self)
680c680
< _multiprocessing.SemLock.__enter__
---
> _multiprocess.SemLock.__enter__
686c686
< _multiprocessing_SemLock___enter___impl(SemLockObject *self)
---
> _multiprocess_SemLock___enter___impl(SemLockObject *self)
689c689
<     return _multiprocessing_SemLock_acquire_impl(self, 1, Py_None);
---
>     return _multiprocess_SemLock_acquire_impl(self, 1, Py_None);
693c693
< _multiprocessing.SemLock.__exit__
---
> _multiprocess.SemLock.__exit__
704c704
< _multiprocessing_SemLock___exit___impl(SemLockObject *self,
---
> _multiprocess_SemLock___exit___impl(SemLockObject *self,
709c709
<     return _multiprocessing_SemLock_release_impl(self);
---
>     return _multiprocess_SemLock_release_impl(self);
724,733c724,733
<     _MULTIPROCESSING_SEMLOCK_ACQUIRE_METHODDEF
<     _MULTIPROCESSING_SEMLOCK_RELEASE_METHODDEF
<     _MULTIPROCESSING_SEMLOCK___ENTER___METHODDEF
<     _MULTIPROCESSING_SEMLOCK___EXIT___METHODDEF
<     _MULTIPROCESSING_SEMLOCK__COUNT_METHODDEF
<     _MULTIPROCESSING_SEMLOCK__IS_MINE_METHODDEF
<     _MULTIPROCESSING_SEMLOCK__GET_VALUE_METHODDEF
<     _MULTIPROCESSING_SEMLOCK__IS_ZERO_METHODDEF
<     _MULTIPROCESSING_SEMLOCK__REBUILD_METHODDEF
<     _MULTIPROCESSING_SEMLOCK__AFTER_FORK_METHODDEF
---
>     _MULTIPROCESS_SEMLOCK_ACQUIRE_METHODDEF
>     _MULTIPROCESS_SEMLOCK_RELEASE_METHODDEF
>     _MULTIPROCESS_SEMLOCK___ENTER___METHODDEF
>     _MULTIPROCESS_SEMLOCK___EXIT___METHODDEF
>     _MULTIPROCESS_SEMLOCK__COUNT_METHODDEF
>     _MULTIPROCESS_SEMLOCK__IS_MINE_METHODDEF
>     _MULTIPROCESS_SEMLOCK__GET_VALUE_METHODDEF
>     _MULTIPROCESS_SEMLOCK__IS_ZERO_METHODDEF
>     _MULTIPROCESS_SEMLOCK__REBUILD_METHODDEF
>     _MULTIPROCESS_SEMLOCK__AFTER_FORK_METHODDEF
764c764
<     {Py_tp_new, _multiprocessing_SemLock},
---
>     {Py_tp_new, _multiprocess_SemLock},
772c772
<     .name = "_multiprocessing.SemLock",
---
>     .name = "_multiprocess.SemLock",
diff ~/src/Python-3.13.0a1/Modules/_multiprocessing/multiprocessing.h Modules/_multiprocess/multiprocess.h 
1,2c1,2
< #ifndef MULTIPROCESSING_H
< #define MULTIPROCESSING_H
---
> #ifndef MULTIPROCESS_H
> #define MULTIPROCESS_H
104c104
< #endif /* MULTIPROCESSING_H */
---
> #endif /* MULTIPROCESS_H */
diff ~/src/Python-3.13.0a1/Modules/_multiprocessing/multiprocessing.c Modules/_multiprocess/multiprocess.c
2c2
<  * Extension module used by multiprocessing package
---
>  * Extension module used by multiprocess package
4c4
<  * multiprocessing.c
---
>  * multiprocess.c
10c10
< #include "multiprocessing.h"
---
> #include "multiprocess.h"
30c30
< module _multiprocessing
---
> module _multiprocess
77c77
< _multiprocessing.closesocket
---
> _multiprocess.closesocket
85c85
< _multiprocessing_closesocket_impl(PyObject *module, HANDLE handle)
---
> _multiprocess_closesocket_impl(PyObject *module, HANDLE handle)
100c100
< _multiprocessing.recv
---
> _multiprocess.recv
109c109
< _multiprocessing_recv_impl(PyObject *module, HANDLE handle, int size)
---
> _multiprocess_recv_impl(PyObject *module, HANDLE handle, int size)
132c132
< _multiprocessing.send
---
> _multiprocess.send
141c141
< _multiprocessing_send_impl(PyObject *module, HANDLE handle, Py_buffer *buf)
---
> _multiprocess_send_impl(PyObject *module, HANDLE handle, Py_buffer *buf)
160c160
< _multiprocessing.sem_unlink
---
> _multiprocess.sem_unlink
168c168
< _multiprocessing_sem_unlink_impl(PyObject *module, const char *name)
---
> _multiprocess_sem_unlink_impl(PyObject *module, const char *name)
196c196
< multiprocessing_exec(PyObject *module)
---
> multiprocess_exec(PyObject *module)
277,278c277,278
< static PyModuleDef_Slot multiprocessing_slots[] = {
<     {Py_mod_exec, multiprocessing_exec},
---
> static PyModuleDef_Slot multiprocess_slots[] = {
>     {Py_mod_exec, multiprocess_exec},
283c283
< static struct PyModuleDef multiprocessing_module = {
---
> static struct PyModuleDef multiprocess_module = {
285c285
<     .m_name = "_multiprocessing",
---
>     .m_name = "_multiprocess",
288c288
<     .m_slots = multiprocessing_slots,
---
>     .m_slots = multiprocess_slots,
292c292
< PyInit__multiprocessing(void)
---
> PyInit__multiprocess(void)
294c294
<     return PyModuleDef_Init(&multiprocessing_module);
---
>     return PyModuleDef_Init(&multiprocess_module);
# ----------------------------------------------------------------------
diff Python-3.12.0rc3/Lib/multiprocessing/connection.py Python-3.13.0a1/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.12.0rc3/Lib/multiprocessing/managers.py Python-3.13.0a1/Lib/multiprocessing/managers.py
93c93,96
<     raise convert_to_error(kind, result)
---
>     try:
>         raise convert_to_error(kind, result)
>     finally:
>         del result  # break reference cycle
836c839,842
<         raise convert_to_error(kind, result)
---
>         try:
>             raise convert_to_error(kind, result)
>         finally:
>             del result   # break reference cycle
diff Python-3.12.0rc3/Lib/multiprocessing/pool.py Python-3.13.0a1/Lib/multiprocessing/pool.py
203c203
<             processes = os.cpu_count() or 1
---
>             processes = os.process_cpu_count() or 1
diff Python-3.12.0rc3/Lib/multiprocessing/popen_spawn_win32.py Python-3.13.0a1/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.12.0rc3/Lib/multiprocessing/queues.py Python-3.13.0a1/Lib/multiprocessing/queues.py
160a161,174
>     def _terminate_broken(self):
>         # Close a Queue on error.
> 
>         # gh-94777: Prevent queue writing to a pipe which is no longer read.
>         self._reader.close()
> 
>         # gh-107219: Close the connection writer which can unblock
>         # Queue._feed() if it was stuck in send_bytes().
>         if sys.platform == 'win32':
>             self._writer.close()
> 
>         self.close()
>         self.join_thread()
> 
172c186,187
<             name='QueueFeederThread'
---
>             name='QueueFeederThread',
>             daemon=True,
174d188
<         self._thread.daemon = True
176,178c190,198
<         debug('doing self._thread.start()')
<         self._thread.start()
<         debug('... done self._thread.start()')
---
>         try:
>             debug('doing self._thread.start()')
>             self._thread.start()
>             debug('... done self._thread.start()')
>         except:
>             # gh-109047: During Python finalization, creating a thread
>             # can fail with RuntimeError.
>             self._thread = None
>             raise
diff Python-3.12.0rc3/Lib/multiprocessing/resource_tracker.py Python-3.13.0a1/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
> 
224,226c254,257
<                     warnings.warn('resource_tracker: There appear to be %d '
<                                   'leaked %s objects to clean up at shutdown' %
<                                   (len(rtype_cache), rtype))
---
>                     warnings.warn(
>                         f'resource_tracker: There appear to be {len(rtype_cache)} '
>                         f'leaked {rtype} objects to clean up at shutdown: {rtype_cache}'
>                     )
diff Python-3.12.0rc3/Lib/multiprocessing/util.py Python-3.13.0a1/Lib/multiprocessing/util.py
67,68c67
<     logging._acquireLock()
<     try:
---
>     with logging._lock:
82,84d80
<     finally:
<         logging._releaseLock()
< 
# ----------------------------------------------------------------------
diff Python-3.12.0rc3/Lib/test/_test_multiprocessing.py Python-3.13.0a1/Lib/test/_test_multiprocessing.py 
53c53
< from multiprocessing.connection import wait, AuthenticationError
---
> from multiprocessing.connection import wait
81,82c81,82
< if support.check_sanitizer(address=True):
<     # bpo-45200: Skip multiprocessing tests if Python is built with ASAN to
---
> if support.HAVE_ASAN_FORK_BUG:
>     # gh-89363: Skip multiprocessing tests if Python is built with ASAN to
84c84,89
<     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
560,561c565
<         if os.name != 'nt':
<             self.assertEqual(exitcode, -signal.SIGTERM)
---
>         self.assertEqual(exitcode, -signal.SIGTERM)
566a571,572
>         else:
>             self.assertEqual(exitcode, -signal.SIGTERM)
1653c1659
<             expected = 0.1
---
>             expected = 0.100
1657,1658c1663
<             # 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:
1677c1682
<             time.sleep(0.01)
---
>             time.sleep(0.010)
2576c2581
<         res = self.pool.apply_async(sqr, (6, TIMEOUT2 + 1.0))
---
>         res = self.pool.apply_async(sqr, (6, TIMEOUT2 + support.SHORT_TIMEOUT))
2680,2682c2685,2687
<         result = self.pool.map_async(
<             time.sleep, [0.1 for i in range(10000)], chunksize=1
<             )
---
>         # Simulate slow tasks which take "forever" to complete
>         args = [support.LONG_TIMEOUT for i in range(10_000)]
>         result = self.pool.map_async(time.sleep, args, chunksize=1)
2684,2687c2689
<         join = TimingWrapper(self.pool.join)
<         join()
<         # Sanity check the pool didn't wait for all tasks to finish
<         self.assertLess(join.elapsed, 2.0)
---
>         self.pool.join()
3153a3156,3193
> 
> class FakeConnection:
>     def send(self, payload):
>         pass
> 
>     def recv(self):
>         return '#ERROR', pyqueue.Empty()
> 
> class TestManagerExceptions(unittest.TestCase):
>     # Issue 106558: Manager exceptions avoids creating cyclic references.
>     def setUp(self):
>         self.mgr = multiprocessing.Manager()
> 
>     def tearDown(self):
>         self.mgr.shutdown()
>         self.mgr.join()
> 
>     def test_queue_get(self):
>         queue = self.mgr.Queue()
>         if gc.isenabled():
>             gc.disable()
>             self.addCleanup(gc.enable)
>         try:
>             queue.get_nowait()
>         except pyqueue.Empty as e:
>             wr = weakref.ref(e)
>         self.assertEqual(wr(), None)
> 
>     def test_dispatch(self):
>         if gc.isenabled():
>             gc.disable()
>             self.addCleanup(gc.enable)
>         try:
>             multiprocessing.managers.dispatch(FakeConnection(), None, None)
>         except pyqueue.Empty as e:
>             wr = weakref.ref(e)
>         self.assertEqual(wr(), None)
> 
4872c4912
<                 time.sleep(random.random()*0.1)
---
>                 time.sleep(random.random() * 0.100)
4912c4952
<                 time.sleep(random.random()*0.1)
---
>                 time.sleep(random.random() * 0.100)
4961c5001
<         expected = 5
---
>         timeout = 5.0  # seconds
4965c5005
<         res = wait([a, b], expected)
---
>         res = wait([a, b], timeout)
4969,4970c5009
<         self.assertLess(delta, expected * 2)
<         self.assertGreater(delta, expected * 0.5)
---
>         self.assertGreater(delta, timeout - CLOCK_RES)
4973,4974d5011
< 
<         start = time.monotonic()
4976,4977d5012
<         delta = time.monotonic() - start
< 
4979d5013
<         self.assertLess(delta, 0.4)
5437c5471,5473
<         self.assertEqual(results, [2, 1])
---
>         # 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]))
# ----------------------------------------------------------------------
diff Python-3.13.0a1/Modules/_multiprocessing/clinic/posixshmem.c.h Python-3.13.0a2/Modules/_multiprocessing/clinic/posixshmem.c.h
5,9d4
< #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
< #  include "pycore_gc.h"          // PyGC_Head
< #  include "pycore_runtime.h"     // _Py_ID()
< #endif
< 
19c14
<     {"shm_open", _PyCFunction_CAST(_posixshmem_shm_open), METH_FASTCALL|METH_KEYWORDS, _posixshmem_shm_open__doc__},
---
>     {"shm_open", (PyCFunction)(void(*)(void))_posixshmem_shm_open, METH_VARARGS|METH_KEYWORDS, _posixshmem_shm_open__doc__},
26c21
< _posixshmem_shm_open(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
---
> _posixshmem_shm_open(PyObject *module, PyObject *args, PyObject *kwargs)
29,55c24
<     #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
< 
<     #define NUM_KEYWORDS 3
<     static struct {
<         PyGC_Head _this_is_not_used;
<         PyObject_VAR_HEAD
<         PyObject *ob_item[NUM_KEYWORDS];
<     } _kwtuple = {
<         .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
<         .ob_item = { &_Py_ID(path), &_Py_ID(flags), &_Py_ID(mode), },
<     };
<     #undef NUM_KEYWORDS
<     #define KWTUPLE (&_kwtuple.ob_base.ob_base)
< 
<     #else  // !Py_BUILD_CORE
<     #  define KWTUPLE NULL
<     #endif  // !Py_BUILD_CORE
< 
<     static const char * const _keywords[] = {"path", "flags", "mode", NULL};
<     static _PyArg_Parser _parser = {
<         .keywords = _keywords,
<         .fname = "shm_open",
<         .kwtuple = KWTUPLE,
<     };
<     #undef KWTUPLE
<     PyObject *argsbuf[3];
<     Py_ssize_t noptargs = nargs + (kwnames ? PyTuple_GET_SIZE(kwnames) : 0) - 2;
---
>     static char *_keywords[] = {"path", "flags", "mode", NULL};
61,78c30,31
<     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 2, 3, 0, argsbuf);
<     if (!args) {
<         goto exit;
<     }
<     if (!PyUnicode_Check(args[0])) {
<         _PyArg_BadArgument("shm_open", "argument 'path'", "str", args[0]);
<         goto exit;
<     }
<     path = args[0];
<     flags = PyLong_AsInt(args[1]);
<     if (flags == -1 && PyErr_Occurred()) {
<         goto exit;
<     }
<     if (!noptargs) {
<         goto skip_optional_pos;
<     }
<     mode = PyLong_AsInt(args[2]);
<     if (mode == -1 && PyErr_Occurred()) {
---
>     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Ui|i:shm_open", _keywords,
>         &path, &flags, &mode))
80,81d32
<     }
< skip_optional_pos:
107c58
<     {"shm_unlink", _PyCFunction_CAST(_posixshmem_shm_unlink), METH_FASTCALL|METH_KEYWORDS, _posixshmem_shm_unlink__doc__},
---
>     {"shm_unlink", (PyCFunction)(void(*)(void))_posixshmem_shm_unlink, METH_VARARGS|METH_KEYWORDS, _posixshmem_shm_unlink__doc__},
113c64
< _posixshmem_shm_unlink(PyObject *module, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames)
---
> _posixshmem_shm_unlink(PyObject *module, PyObject *args, PyObject *kwargs)
116,141c67
<     #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
< 
<     #define NUM_KEYWORDS 1
<     static struct {
<         PyGC_Head _this_is_not_used;
<         PyObject_VAR_HEAD
<         PyObject *ob_item[NUM_KEYWORDS];
<     } _kwtuple = {
<         .ob_base = PyVarObject_HEAD_INIT(&PyTuple_Type, NUM_KEYWORDS)
<         .ob_item = { &_Py_ID(path), },
<     };
<     #undef NUM_KEYWORDS
<     #define KWTUPLE (&_kwtuple.ob_base.ob_base)
< 
<     #else  // !Py_BUILD_CORE
<     #  define KWTUPLE NULL
<     #endif  // !Py_BUILD_CORE
< 
<     static const char * const _keywords[] = {"path", NULL};
<     static _PyArg_Parser _parser = {
<         .keywords = _keywords,
<         .fname = "shm_unlink",
<         .kwtuple = KWTUPLE,
<     };
<     #undef KWTUPLE
<     PyObject *argsbuf[1];
---
>     static char *_keywords[] = {"path", NULL};
144,145c70,71
<     args = _PyArg_UnpackKeywords(args, nargs, NULL, kwnames, &_parser, 1, 1, 0, argsbuf);
<     if (!args) {
---
>     if (!PyArg_ParseTupleAndKeywords(args, kwargs, "U:shm_unlink", _keywords,
>         &path))
147,152d72
<     }
<     if (!PyUnicode_Check(args[0])) {
<         _PyArg_BadArgument("shm_unlink", "argument 'path'", "str", args[0]);
<         goto exit;
<     }
<     path = args[0];
168c88
< /*[clinic end generated code: output=2f356903a281d857 input=a9049054013a1b77]*/
---
> /*[clinic end generated code: output=be0661dbed83ea23 input=a9049054013a1b77]*/
diff Python-3.13.0a1/Modules/_multiprocessing/clinic/semaphore.c.h Python-3.13.0a2/Modules/_multiprocessing/clinic/semaphore.c.h
8a9
> #include "pycore_modsupport.h"    // _PyArg_UnpackKeywords()
544c545
< /*[clinic end generated code: output=e8ea65f8cba8e173 input=a9049054013a1b77]*/
---
> /*[clinic end generated code: output=d57992037e6770b6 input=a9049054013a1b77]*/
diff Python-3.13.0a1/Modules/_multiprocessing/clinic/multiprocessing.c.h Python-3.13.0a2/Modules/_multiprocessing/clinic/multiprocessing.c.h
4a5,6
> #include "pycore_modsupport.h"    // _PyArg_CheckPositional()
> 
105,108d106
<     if (!PyBuffer_IsContiguous(&buf, 'C')) {
<         _PyArg_BadArgument("send", "argument 2", "contiguous buffer", args[1]);
<         goto exit;
<     }
169c167
< /*[clinic end generated code: output=8b91c020d4353cc5 input=a9049054013a1b77]*/
---
> /*[clinic end generated code: output=73b4cb8428d816da input=a9049054013a1b77]*/
# ----------------------------------------------------------------------
diff Python-3.13.0a1/Modules/_multiprocessing/posixshmem.c Python-3.13.0a2/Modules/_multiprocessing/posixshmem.c
4a5,11
> #include "pyconfig.h"   // Py_GIL_DISABLED
> 
> #ifndef Py_GIL_DISABLED
> // Need limited C API version 3.12 for Py_MOD_PER_INTERPRETER_GIL_SUPPORTED
> #define Py_LIMITED_API 0x030c0000
> #endif
> 
7c14
< // for shm_open() and shm_unlink()
---
> #include <errno.h>                // EINTR
9c16
< #include <sys/mman.h>
---
> #  include <sys/mman.h>           // shm_open(), shm_unlink()
11a19
> 
43c51
<     const char *name = PyUnicode_AsUTF8(path);
---
>     const char *name = PyUnicode_AsUTF8AndSize(path, NULL);
82c90
<     const char *name = PyUnicode_AsUTF8(path);
---
>     const char *name = PyUnicode_AsUTF8AndSize(path, NULL);
# ----------------------------------------------------------------------
diff Python-3.13.0a1/Lib/multiprocessing/managers.py Python-3.13.0a2/Lib/multiprocessing/managers.py
1167a1168
>     __class_getitem__ = classmethod(types.GenericAlias)
1169c1170,1171
< DictProxy = MakeProxyType('DictProxy', (
---
> 
> _BaseDictProxy = MakeProxyType('DictProxy', (
1174c1176
< DictProxy._method_to_typeid_ = {
---
> _BaseDictProxy._method_to_typeid_ = {
1176a1179,1180
> class DictProxy(_BaseDictProxy):
>     __class_getitem__ = classmethod(types.GenericAlias)
# ----------------------------------------------------------------------
diff Python-3.13.0a1/Lib/test/_test_multiprocessing.py Python-3.13.0a2/Lib/test/_test_multiprocessing.py 
2441,2442c2441,2445
< 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)
2581,2584c2584,2595
<         res = self.pool.apply_async(sqr, (6, TIMEOUT2 + support.SHORT_TIMEOUT))
<         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()
2684a2696,2698
>         if self.TYPE == 'threads':
>             self.skipTest("Threads cannot be terminated")
> 
2685a2700
>         p = self.Pool(3)
2687,2689c2702,2704
<         result = self.pool.map_async(time.sleep, args, chunksize=1)
<         self.pool.terminate()
<         self.pool.join()
---
>         result = p.map_async(time.sleep, args, chunksize=1)
>         p.terminate()
>         p.join()
# ----------------------------------------------------------------------
diff Python-3.13.0a2/Lib/multiprocessing/managers.py Python-3.13.0a3/Lib/multiprocessing/managers.py
159c159
<         self.listener = Listener(address=address, backlog=16)
---
>         self.listener = Listener(address=address, backlog=128)
diff Python-3.13.0a2/Lib/multiprocessing/popen_spawn_win32.py Python-3.13.0a3/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.13.0a2/Lib/multiprocessing/resource_sharer.py Python-3.13.0a3/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.13.0a2/Lib/multiprocessing/shared_memory.py Python-3.13.0a3/Lib/multiprocessing/shared_memory.py
73a74
>     _track = True
75c76
<     def __init__(self, name=None, create=False, size=0):
---
>     def __init__(self, name=None, create=False, size=0, *, track=True):
84a86
>         self._track = track
119,120c121,122
< 
<             resource_tracker.register(self._name, "shared_memory")
---
>             if self._track:
>                 resource_tracker.register(self._name, "shared_memory")
239,241c241,250
<         In order to ensure proper cleanup of resources, unlink should be
<         called once (and only once) across all processes which have access
<         to the shared memory block."""
---
>         Unlink should be called once (and only once) across all handles
>         which have access to the shared memory block, even if these
>         handles belong to different processes. Closing and unlinking may
>         happen in any order, but trying to access data inside a shared
>         memory block after unlinking may result in memory errors,
>         depending on platform.
> 
>         This method has no effect on Windows, where the only way to
>         delete a shared memory block is to close all handles."""
> 
244c253,254
<             resource_tracker.unregister(self._name, "shared_memory")
---
>             if self._track:
>                 resource_tracker.unregister(self._name, "shared_memory")
diff Python-3.13.0a2/Lib/multiprocessing/util.py Python-3.13.0a3/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)
# ----------------------------------------------------------------------
diff Python-3.13.0a2/Lib/test/_test_multiprocessing.py Python-3.13.0a3/Lib/test/_test_multiprocessing.py 
4457a4458,4510
>     @unittest.skipIf(os.name != "posix", "resource_tracker is posix only")
>     def test_shared_memory_untracking(self):
>         # gh-82300: When a separate Python process accesses shared memory
>         # with track=False, it must not cause the memory to be deleted
>         # when terminating.
>         cmd = '''if 1:
>             import sys
>             from multiprocessing.shared_memory import SharedMemory
>             mem = SharedMemory(create=False, name=sys.argv[1], track=False)
>             mem.close()
>         '''
>         mem = shared_memory.SharedMemory(create=True, size=10)
>         # The resource tracker shares pipes with the subprocess, and so
>         # err existing means that the tracker process has terminated now.
>         try:
>             rc, out, err = script_helper.assert_python_ok("-c", cmd, mem.name)
>             self.assertNotIn(b"resource_tracker", err)
>             self.assertEqual(rc, 0)
>             mem2 = shared_memory.SharedMemory(create=False, name=mem.name)
>             mem2.close()
>         finally:
>             try:
>                 mem.unlink()
>             except OSError:
>                 pass
>             mem.close()
> 
>     @unittest.skipIf(os.name != "posix", "resource_tracker is posix only")
>     def test_shared_memory_tracking(self):
>         # gh-82300: When a separate Python process accesses shared memory
>         # with track=True, it must cause the memory to be deleted when
>         # terminating.
>         cmd = '''if 1:
>             import sys
>             from multiprocessing.shared_memory import SharedMemory
>             mem = SharedMemory(create=False, name=sys.argv[1], track=True)
>             mem.close()
>         '''
>         mem = shared_memory.SharedMemory(create=True, size=10)
>         try:
>             rc, out, err = script_helper.assert_python_ok("-c", cmd, mem.name)
>             self.assertEqual(rc, 0)
>             self.assertIn(
>                 b"resource_tracker: There appear to be 1 leaked "
>                 b"shared_memory objects to clean up at shutdown", err)
>         finally:
>             try:
>                 mem.unlink()
>             except OSError:
>                 pass
>             resource_tracker.unregister(mem._name, "shared_memory")
>             mem.close()
> 
4673a4727,4749
>     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()
> 

