https://github.com/python/cpython/commit/82d3439f7cc243b5f8a82d3d1c5c03ad03f8ff80
commit: 82d3439f7cc243b5f8a82d3d1c5c03ad03f8ff80
branch: main
author: Gregory P. Smith <[email protected]>
committer: gpshead <[email protected]>
date: 2026-11-01T18:35:40Z
summary:
gh-161098: Unlink the new ShareableList block if packing a value fails
(GH-161099)
ShareableList(sequence) created its shared memory block before packing the
values, so an unpackable value (an int outside int64, a lone surrogate)
left the block behind with no way for the caller to release it.
files:
A Misc/NEWS.d/next/Library/2026-10-22-05-20-27.gh-issue-161098.voMVnd.rst
M Lib/multiprocessing/shared_memory.py
M Lib/test/_test_multiprocessing.py
diff --git a/Lib/multiprocessing/shared_memory.py
b/Lib/multiprocessing/shared_memory.py
index 582a00a32facff7..b5396451d0e64a5 100644
--- a/Lib/multiprocessing/shared_memory.py
+++ b/Lib/multiprocessing/shared_memory.py
@@ -349,31 +349,40 @@ def __init__(self, sequence=None, *, name=None):
if sequence is not None:
_enc = _encoding
- struct.pack_into(
- "q" + self._format_size_metainfo,
- self.shm.buf,
- 0,
- self._list_len,
- *(self._allocated_offsets)
- )
- struct.pack_into(
- "".join(_formats),
- self.shm.buf,
- self._offset_data_start,
- *(self._encode_value(v) for v in sequence)
- )
- struct.pack_into(
- self._format_packing_metainfo,
- self.shm.buf,
- self._offset_packing_formats,
- *(v.encode(_enc) for v in _formats)
- )
- struct.pack_into(
- self._format_back_transform_codes,
- self.shm.buf,
- self._offset_back_transform_codes,
- *(_recreation_codes)
- )
+ try:
+ struct.pack_into(
+ "q" + self._format_size_metainfo,
+ self.shm.buf,
+ 0,
+ self._list_len,
+ *(self._allocated_offsets)
+ )
+ struct.pack_into(
+ "".join(_formats),
+ self.shm.buf,
+ self._offset_data_start,
+ *(self._encode_value(v) for v in sequence)
+ )
+ struct.pack_into(
+ self._format_packing_metainfo,
+ self.shm.buf,
+ self._offset_packing_formats,
+ *(v.encode(_enc) for v in _formats)
+ )
+ struct.pack_into(
+ self._format_back_transform_codes,
+ self.shm.buf,
+ self._offset_back_transform_codes,
+ *(_recreation_codes)
+ )
+ except BaseException:
+ # A value of a supported type may still be unpackable, such as
+ # an int outside the signed 64-bit range. The block was
created
+ # above and the caller gets no object to release it with, so
+ # destroy it here.
+ self.shm.close()
+ self.shm.unlink()
+ raise
else:
self._list_len = len(self) # Obtains size from offset 0 in buffer.
diff --git a/Lib/test/_test_multiprocessing.py
b/Lib/test/_test_multiprocessing.py
index e3e0d11fa79f754..44e66707607ab57 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -5218,6 +5218,23 @@ def test_shared_memory_ShareableList_basics(self):
finally:
empty_sl.shm.unlink()
+ def test_shared_memory_ShareableList_unpackable_value(self):
+ # Values of a supported type that cannot be packed must not leave
+ # the newly created shared memory block behind.
+ name = self._new_shm_name('test03_unpackable')
+ for value, exc in (
+ (2**63, struct.error),
+ (-2**63 - 1, struct.error),
+ ):
+ with self.subTest(value=value):
+ with self.assertRaises(exc):
+ shared_memory.ShareableList(['abc', value], name=name)
+ if sys.platform != "win32":
+ with self.assertRaises(FileNotFoundError):
+ # Should not be there to be attached to.
+ leftover = shared_memory.SharedMemory(name)
+ leftover.unlink() # Error should occur on prior line.
+
def test_shared_memory_ShareableList_pickling(self):
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
with self.subTest(proto=proto):
diff --git
a/Misc/NEWS.d/next/Library/2026-10-22-05-20-27.gh-issue-161098.voMVnd.rst
b/Misc/NEWS.d/next/Library/2026-10-22-05-20-27.gh-issue-161098.voMVnd.rst
new file mode 100644
index 000000000000000..73849a0136aafcc
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-22-05-20-27.gh-issue-161098.voMVnd.rst
@@ -0,0 +1,3 @@
+Fix :class:`multiprocessing.shared_memory.ShareableList` leaving its newly
+created shared memory block behind when a value cannot be stored, such as an
+integer outside the signed 64-bit range.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]