| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent dcf2c3b commit 1b3fedd
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -119,6 +119,10 @@ def _lock_file_path(self): | |||
| 119 | 119 | """ | |
| 120 | 120 | return "%s.lock" % (self._file_path) | |
| 121 | 121 | ||
| 122 | + def _get_id(self): | ||
| 123 | + """Returns string id to be written into the lock file""" | ||
| 124 | + return "%i|%i" % (os.getpid(), hash(self)) | ||
| 125 | + | ||
| 122 | 126 | def _has_lock(self): | |
| 123 | 127 | """ | |
| 124 | 128 | Return | |
@@ -133,13 +137,13 @@ def _has_lock(self): | |||
| 133 | 137 | lock_file = self._lock_file_path() | |
| 134 | 138 | try: | |
| 135 | 139 | fp = open(lock_file, "rb") | |
| 136 | - pid = int(fp.read()) | ||
| 140 | + pid = fp.read() | ||
| 137 | 141 | fp.close() | |
| 138 | 142 | except IOError: | |
| 139 | 143 | raise AssertionError("The lock file at %s could not be read" % lock_file) | |
| 140 | 144 | ||
| 141 | - if pid != os.getpid(): | ||
| 142 | - raise AssertionError("We claim to own the lock at %s, but it was not owned by our process %i, but by %i" % (lock_file, os.getpid(), pid)) | ||
| 145 | + if pid != self._get_id(): | ||
| 146 | + raise AssertionError("We claim to own the lock at %s, but it was not owned by our process %r, but by %r" % (lock_file, self._get_id(), pid )) | ||
| 143 | 147 | ||
| 144 | 148 | return True | |
| 145 | 149 | ||
@@ -152,14 +156,25 @@ def _obtain_lock_or_raise(self): | |||
| 152 | 156 | """ | |
| 153 | 157 | if self._has_lock(): | |
| 154 | 158 | return | |
| 155 | - | ||
| 156 | 159 | lock_file = self._lock_file_path() | |
| 157 | - if os.path.exists(lock_file): | ||
| 160 | + if os.path.isfile(lock_file): | ||
| 158 | 161 | raise IOError("Lock for file %r did already exist, delete %r in case the lock is illegal" % (self._file_path, lock_file)) | |
| 159 | - | ||
| 162 | + | ||
| 163 | + my_id = self._get_id() | ||
| 160 | 164 | fp = open(lock_file, "wb") | |
| 161 | - fp.write(str(os.getpid())) | ||
| 165 | + fp.write(my_id) | ||
| 166 | + fp.close() | ||
| 167 | + | ||
| 168 | + # verify its truly us who got the lock - if two threads are doing this within the | ||
| 169 | + # fraction of a millisecond, it is possible to actually trick the FS | ||
| 170 | + # and two threads write, but only one succeeds. | ||
| 171 | + fp = open(lock_file, 'rb') | ||
| 172 | + actual_id = fp.read() | ||
| 162 | 173 | fp.close() | |
| 174 | + if actual_id != my_id: | ||
| 175 | + msg = "Failed to obtain lock for file %r as the process identified by %r outraced this process or thread %r" % (self._file_path, actual_id, my_id) | ||
| 176 | + raise IOError(msg) | ||
| 177 | + # END verification | ||
| 163 | 178 | ||
| 164 | 179 | self._owns_lock = True | |
| 165 | 180 | ||
@@ -175,11 +190,11 @@ def _release_lock(self): | |||
| 175 | 190 | Release our lock if we have one | |
| 176 | 191 | """ | |
| 177 | 192 | if not self._has_lock(): | |
| 178 | - return | ||
| 179 | - | ||
| 193 | + return | ||
| 180 | 194 | os.remove(self._lock_file_path()) | |
| 181 | 195 | self._owns_lock = False | |
| 182 | 196 | ||
| 197 | + | ||
| 183 | 198 | class BlockingLockFile(LockFile): | |
| 184 | 199 | """The lock file will block until a lock could be obtained, or fail after | |
| 185 | 200 | a specified timeout""" | |
@@ -206,7 +221,7 @@ def _obtain_lock(self): | |||
| 206 | 221 | maxtime = starttime + float(self._max_block_time) | |
| 207 | 222 | while True: | |
| 208 | 223 | try: | |
| 209 | - self._obtain_lock_or_raise() | ||
| 224 | + super(BlockingLockFile, self)._obtain_lock() | ||
| 210 | 225 | except IOError: | |
| 211 | 226 | curtime = time.time() | |
| 212 | 227 | if curtime >= maxtime: | |
@@ -219,7 +234,6 @@ def _obtain_lock(self): | |||
| 219 | 234 | # END endless loop | |
| 220 | 235 | ||
| 221 | 236 | ||
| 222 | - | ||
| 223 | 237 | class ConcurrentWriteOperation(LockFile): | |
| 224 | 238 | """ | |
| 225 | 239 | This class facilitates a safe write operation to a file on disk such that we: | |
| Back | FazBrowse Home | New Git URL |
0 commit comments