1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
from abc import ABC
from abc import abstractmethod
import errno
import os
class _InterProcessReaderWriterLockMechanism(ABC):
@staticmethod
@abstractmethod
def trylock(lockfile, exclusive):
...
@staticmethod
@abstractmethod
def unlock(lockfile):
...
@staticmethod
@abstractmethod
def get_handle(path):
...
@staticmethod
@abstractmethod
def close_handle(lockfile):
...
class _InterProcessMechanism(ABC):
@staticmethod
@abstractmethod
def trylock(lockfile):
...
@staticmethod
@abstractmethod
def unlock(lockfile):
...
class _WindowsInterProcessMechanism(_InterProcessMechanism):
"""Interprocess lock implementation that works on windows systems."""
@staticmethod
def trylock(lockfile):
fileno = lockfile.fileno()
msvcrt.locking(fileno, msvcrt.LK_NBLCK, 1)
@staticmethod
def unlock(lockfile):
fileno = lockfile.fileno()
msvcrt.locking(fileno, msvcrt.LK_UNLCK, 1)
class _FcntlInterProcessMechanism(_InterProcessMechanism):
"""Interprocess lock implementation that works on posix systems."""
@staticmethod
def trylock(lockfile):
fcntl.lockf(lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
@staticmethod
def unlock(lockfile):
fcntl.lockf(lockfile, fcntl.LOCK_UN)
class _WindowsInterProcessReaderWriterLockMechanism(_InterProcessReaderWriterLockMechanism):
"""Interprocess readers writer lock implementation that works on windows
systems."""
@staticmethod
def trylock(lockfile, exclusive):
if exclusive:
flags = win32con.LOCKFILE_FAIL_IMMEDIATELY | win32con.LOCKFILE_EXCLUSIVE_LOCK
else:
flags = win32con.LOCKFILE_FAIL_IMMEDIATELY
handle = msvcrt.get_osfhandle(lockfile.fileno())
ok = win32file.LockFileEx(handle, flags, 0, 1, 0, win32file.pointer(pywintypes.OVERLAPPED()))
if ok:
return True
else:
last_error = win32file.GetLastError()
if last_error == win32file.ERROR_LOCK_VIOLATION:
return False
else:
raise OSError(last_error)
@staticmethod
def unlock(lockfile):
handle = msvcrt.get_osfhandle(lockfile.fileno())
ok = win32file.UnlockFileEx(handle, 0, 1, 0, win32file.pointer(pywintypes.OVERLAPPED()))
if not ok:
raise OSError(win32file.GetLastError())
@staticmethod
def get_handle(path):
return open(path, 'a+')
@staticmethod
def close_handle(lockfile):
lockfile.close()
class _FcntlInterProcessReaderWriterLockMechanism(_InterProcessReaderWriterLockMechanism):
"""Interprocess readers writer lock implementation that works on posix
systems."""
@staticmethod
def trylock(lockfile, exclusive):
if exclusive:
flags = fcntl.LOCK_EX | fcntl.LOCK_NB
else:
flags = fcntl.LOCK_SH | fcntl.LOCK_NB
try:
fcntl.lockf(lockfile, flags)
return True
except (IOError, OSError) as e:
if e.errno in (errno.EACCES, errno.EAGAIN):
return False
else:
raise e
@staticmethod
def unlock(lockfile):
fcntl.lockf(lockfile, fcntl.LOCK_UN)
@staticmethod
def get_handle(path):
return open(path, 'a+')
@staticmethod
def close_handle(lockfile):
lockfile.close()
if os.name == 'nt':
import msvcrt
import fasteners.pywin32.pywintypes as pywintypes
import fasteners.pywin32.win32con as win32con
import fasteners.pywin32.win32file as win32file
_interprocess_reader_writer_mechanism = _WindowsInterProcessReaderWriterLockMechanism()
_interprocess_mechanism = _WindowsInterProcessMechanism()
else:
import fcntl
_interprocess_reader_writer_mechanism = _FcntlInterProcessReaderWriterLockMechanism()
_interprocess_mechanism = _FcntlInterProcessMechanism()
|