Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 34 additions & 25 deletions Lib/multiprocessing/shared_memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
17 changes: 17 additions & 0 deletions Lib/test/_test_multiprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -4922,6 +4922,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):
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Loading