Kaydet (Commit) f15e5240 authored tarafından Serhiy Storchaka's avatar Serhiy Storchaka

Issue #14099: Writing to ZipFile and reading multiple ZipExtFiles is

threadsafe now.
üst b67c516d
......@@ -13,6 +13,7 @@ import stat
import shutil
import struct
import binascii
import threading
try:
......@@ -647,12 +648,14 @@ def _get_decompressor(compress_type):
class _SharedFile:
def __init__(self, file, pos, close):
def __init__(self, file, pos, close, lock):
self._file = file
self._pos = pos
self._close = close
self._lock = lock
def read(self, n=-1):
with self._lock:
self._file.seek(self._pos)
data = self._file.read(n)
self._pos = self._file.tell()
......@@ -990,6 +993,7 @@ class ZipFile:
self.fp = file
self.filename = getattr(file, 'name', None)
self._fileRefCnt = 1
self._lock = threading.RLock()
try:
if mode == 'r':
......@@ -1214,7 +1218,7 @@ class ZipFile:
zinfo = self.getinfo(name)
self._fileRefCnt += 1
zef_file = _SharedFile(self.fp, zinfo.header_offset, self._fpclose)
zef_file = _SharedFile(self.fp, zinfo.header_offset, self._fpclose, self._lock)
try:
# Skip the file header:
fheader = zef_file.read(sizeFileHeader)
......@@ -1410,6 +1414,7 @@ class ZipFile:
zinfo.file_size = st.st_size
zinfo.flag_bits = 0x00
with self._lock:
self.fp.seek(self.start_dir, 0)
zinfo.header_offset = self.fp.tell() # Start of header bytes
if zinfo.compress_type == ZIP_LZMA:
......@@ -1498,6 +1503,7 @@ class ZipFile:
"Attempt to write to ZIP archive that was already closed")
zinfo.file_size = len(data) # Uncompressed size
with self._lock:
self.fp.seek(self.start_dir, 0)
zinfo.header_offset = self.fp.tell() # Start of header data
if compress_type is not None:
......@@ -1543,6 +1549,15 @@ class ZipFile:
try:
if self.mode in ("w", "a") and self._didModify: # write ending records
with self._lock:
self.fp.seek(self.start_dir, 0)
self._write_end_record()
finally:
fp = self.fp
self.fp = None
self._fpclose(fp)
def _write_end_record(self):
self.fp.seek(self.start_dir, 0)
for zinfo in self.filelist: # write central directory
dt = zinfo.date_time
......@@ -1643,10 +1658,6 @@ class ZipFile:
self.fp.write(endrec)
self.fp.write(self._comment)
self.fp.flush()
finally:
fp = self.fp
self.fp = None
self._fpclose(fp)
def _fpclose(self, fp):
assert self._fileRefCnt > 0
......
......@@ -218,6 +218,9 @@ Core and Builtins
Library
-------
- Issue #14099: Writing to ZipFile and reading multiple ZipExtFiles is
threadsafe now.
- Issue #19361: JSON decoder now raises JSONDecodeError instead of ValueError.
- Issue #18518: timeit now rejects statements which can't be compiled outside
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment