Show More
@@ -102,7 +102,16 class lock(object): | |||||
102 | self.held = 1 |
|
102 | self.held = 1 | |
103 | except (OSError, IOError) as why: |
|
103 | except (OSError, IOError) as why: | |
104 | if why.errno == errno.EEXIST: |
|
104 | if why.errno == errno.EEXIST: | |
105 |
locker = self. |
|
105 | locker = self._readlock() | |
|
106 | # special case where a parent process holds the lock -- this | |||
|
107 | # is different from the pid being different because we do | |||
|
108 | # want the unlock and postrelease functions to be called, | |||
|
109 | # but the lockfile to not be removed. | |||
|
110 | if locker == self.parentlock: | |||
|
111 | self._parentheld = True | |||
|
112 | self.held = 1 | |||
|
113 | return | |||
|
114 | locker = self._testlock(locker) | |||
106 | if locker is not None: |
|
115 | if locker is not None: | |
107 | raise error.LockHeld(errno.EAGAIN, |
|
116 | raise error.LockHeld(errno.EAGAIN, | |
108 | self.vfs.join(self.f), self.desc, |
|
117 | self.vfs.join(self.f), self.desc, |
@@ -151,5 +151,106 class testlock(unittest.TestCase): | |||||
151 | state.assertpostreleasecalled(True) |
|
151 | state.assertpostreleasecalled(True) | |
152 | state.assertlockexists(False) |
|
152 | state.assertlockexists(False) | |
153 |
|
153 | |||
|
154 | def testinheritlock(self): | |||
|
155 | d = tempfile.mkdtemp(dir=os.getcwd()) | |||
|
156 | parentstate = teststate(self, d) | |||
|
157 | parentlock = parentstate.makelock() | |||
|
158 | parentstate.assertacquirecalled(True) | |||
|
159 | ||||
|
160 | # set up lock inheritance | |||
|
161 | lockname = parentlock.prepinherit() | |||
|
162 | parentstate.assertreleasecalled(True) | |||
|
163 | parentstate.assertpostreleasecalled(False) | |||
|
164 | parentstate.assertlockexists(True) | |||
|
165 | ||||
|
166 | childstate = teststate(self, d, pidoffset=1) | |||
|
167 | childlock = childstate.makelock(parentlock=lockname) | |||
|
168 | childstate.assertacquirecalled(True) | |||
|
169 | ||||
|
170 | # release the child lock -- the lock file should still exist on disk | |||
|
171 | childlock.release() | |||
|
172 | childstate.assertreleasecalled(True) | |||
|
173 | childstate.assertpostreleasecalled(True) | |||
|
174 | childstate.assertlockexists(True) | |||
|
175 | ||||
|
176 | parentstate.resetacquirefn() | |||
|
177 | parentlock.reacquire() | |||
|
178 | parentstate.assertacquirecalled(True) | |||
|
179 | ||||
|
180 | parentlock.release() | |||
|
181 | parentstate.assertreleasecalled(True) | |||
|
182 | parentstate.assertpostreleasecalled(True) | |||
|
183 | parentstate.assertlockexists(False) | |||
|
184 | ||||
|
185 | def testmultilock(self): | |||
|
186 | d = tempfile.mkdtemp(dir=os.getcwd()) | |||
|
187 | state0 = teststate(self, d) | |||
|
188 | lock0 = state0.makelock() | |||
|
189 | state0.assertacquirecalled(True) | |||
|
190 | ||||
|
191 | lock0name = lock0.prepinherit() | |||
|
192 | state0.assertreleasecalled(True) | |||
|
193 | state0.assertpostreleasecalled(False) | |||
|
194 | state0.assertlockexists(True) | |||
|
195 | ||||
|
196 | state1 = teststate(self, d, pidoffset=1) | |||
|
197 | lock1 = state1.makelock(parentlock=lock0name) | |||
|
198 | state1.assertacquirecalled(True) | |||
|
199 | ||||
|
200 | # from within lock1, acquire another lock | |||
|
201 | lock1name = lock1.prepinherit() | |||
|
202 | # since the file on disk is lock0's this should have the same name | |||
|
203 | self.assertEqual(lock0name, lock1name) | |||
|
204 | ||||
|
205 | state2 = teststate(self, d, pidoffset=2) | |||
|
206 | lock2 = state2.makelock(parentlock=lock1name) | |||
|
207 | state2.assertacquirecalled(True) | |||
|
208 | ||||
|
209 | lock2.release() | |||
|
210 | state2.assertreleasecalled(True) | |||
|
211 | state2.assertpostreleasecalled(True) | |||
|
212 | state2.assertlockexists(True) | |||
|
213 | ||||
|
214 | state1.resetacquirefn() | |||
|
215 | lock1.reacquire() | |||
|
216 | state1.assertacquirecalled(True) | |||
|
217 | ||||
|
218 | lock1.release() | |||
|
219 | state1.assertreleasecalled(True) | |||
|
220 | state1.assertpostreleasecalled(True) | |||
|
221 | state1.assertlockexists(True) | |||
|
222 | ||||
|
223 | lock0.reacquire() | |||
|
224 | lock0.release() | |||
|
225 | ||||
|
226 | def testinheritlockfork(self): | |||
|
227 | d = tempfile.mkdtemp(dir=os.getcwd()) | |||
|
228 | parentstate = teststate(self, d) | |||
|
229 | parentlock = parentstate.makelock() | |||
|
230 | parentstate.assertacquirecalled(True) | |||
|
231 | ||||
|
232 | # set up lock inheritance | |||
|
233 | lockname = parentlock.prepinherit() | |||
|
234 | childstate = teststate(self, d, pidoffset=1) | |||
|
235 | childlock = childstate.makelock(parentlock=lockname) | |||
|
236 | childstate.assertacquirecalled(True) | |||
|
237 | ||||
|
238 | # fork the child lock | |||
|
239 | forkchildlock = copy.deepcopy(childlock) | |||
|
240 | forkchildlock._pidoffset += 1 | |||
|
241 | forkchildlock.release() | |||
|
242 | childstate.assertreleasecalled(False) | |||
|
243 | childstate.assertpostreleasecalled(False) | |||
|
244 | childstate.assertlockexists(True) | |||
|
245 | ||||
|
246 | # release the child lock | |||
|
247 | childlock.release() | |||
|
248 | childstate.assertreleasecalled(True) | |||
|
249 | childstate.assertpostreleasecalled(True) | |||
|
250 | childstate.assertlockexists(True) | |||
|
251 | ||||
|
252 | parentlock.reacquire() | |||
|
253 | parentlock.release() | |||
|
254 | ||||
154 | if __name__ == '__main__': |
|
255 | if __name__ == '__main__': | |
155 | silenttestrunner.main(__name__) |
|
256 | silenttestrunner.main(__name__) |
General Comments 0
You need to be logged in to leave comments.
Login now