[utils] Improve file locking
* Implement non-blocking locks for windows * Don't raise error when closing a closed file
This commit is contained in:
parent
acea8d7cfb
commit
747c0bd127
1 changed files with 12 additions and 8 deletions
|
@ -2122,22 +2122,22 @@ if sys.platform == 'win32':
|
||||||
whole_low = 0xffffffff
|
whole_low = 0xffffffff
|
||||||
whole_high = 0x7fffffff
|
whole_high = 0x7fffffff
|
||||||
|
|
||||||
def _lock_file(f, exclusive, block): # todo: block unused on win32
|
def _lock_file(f, exclusive, block):
|
||||||
overlapped = OVERLAPPED()
|
overlapped = OVERLAPPED()
|
||||||
overlapped.Offset = 0
|
overlapped.Offset = 0
|
||||||
overlapped.OffsetHigh = 0
|
overlapped.OffsetHigh = 0
|
||||||
overlapped.hEvent = 0
|
overlapped.hEvent = 0
|
||||||
f._lock_file_overlapped_p = ctypes.pointer(overlapped)
|
f._lock_file_overlapped_p = ctypes.pointer(overlapped)
|
||||||
handle = msvcrt.get_osfhandle(f.fileno())
|
|
||||||
if not LockFileEx(handle, 0x2 if exclusive else 0x0, 0,
|
if not LockFileEx(msvcrt.get_osfhandle(f.fileno()),
|
||||||
whole_low, whole_high, f._lock_file_overlapped_p):
|
(0x2 if exclusive else 0x0) | (0x0 if block else 0x1),
|
||||||
raise OSError('Locking file failed: %r' % ctypes.FormatError())
|
0, whole_low, whole_high, f._lock_file_overlapped_p):
|
||||||
|
raise BlockingIOError('Locking file failed: %r' % ctypes.FormatError())
|
||||||
|
|
||||||
def _unlock_file(f):
|
def _unlock_file(f):
|
||||||
assert f._lock_file_overlapped_p
|
assert f._lock_file_overlapped_p
|
||||||
handle = msvcrt.get_osfhandle(f.fileno())
|
handle = msvcrt.get_osfhandle(f.fileno())
|
||||||
if not UnlockFileEx(handle, 0,
|
if not UnlockFileEx(handle, 0, whole_low, whole_high, f._lock_file_overlapped_p):
|
||||||
whole_low, whole_high, f._lock_file_overlapped_p):
|
|
||||||
raise OSError('Unlocking file failed: %r' % ctypes.FormatError())
|
raise OSError('Unlocking file failed: %r' % ctypes.FormatError())
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -2175,6 +2175,8 @@ else:
|
||||||
|
|
||||||
|
|
||||||
class locked_file(object):
|
class locked_file(object):
|
||||||
|
_closed = False
|
||||||
|
|
||||||
def __init__(self, filename, mode, block=True, encoding=None):
|
def __init__(self, filename, mode, block=True, encoding=None):
|
||||||
assert mode in ['r', 'rb', 'a', 'ab', 'w', 'wb']
|
assert mode in ['r', 'rb', 'a', 'ab', 'w', 'wb']
|
||||||
self.f = io.open(filename, mode, encoding=encoding)
|
self.f = io.open(filename, mode, encoding=encoding)
|
||||||
|
@ -2192,9 +2194,11 @@ class locked_file(object):
|
||||||
|
|
||||||
def __exit__(self, etype, value, traceback):
|
def __exit__(self, etype, value, traceback):
|
||||||
try:
|
try:
|
||||||
_unlock_file(self.f)
|
if not self._closed:
|
||||||
|
_unlock_file(self.f)
|
||||||
finally:
|
finally:
|
||||||
self.f.close()
|
self.f.close()
|
||||||
|
self._closed = True
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self.f)
|
return iter(self.f)
|
||||||
|
|
Loading…
Reference in a new issue