diff options
author | nierob <nierob@users.noreply.github.com> | 2018-11-23 15:46:12 (GMT) |
---|---|---|
committer | Victor Stinner <vstinner@redhat.com> | 2018-11-23 15:46:12 (GMT) |
commit | b409ffa848b280c1db1b4f450bfae14f263099ac (patch) | |
tree | 0c240c1514a28c75ad2300852712cfdc31faaf15 /Lib | |
parent | f653fd4d950ac092719b6152e38d77c62b443125 (diff) | |
download | cpython-b409ffa848b280c1db1b4f450bfae14f263099ac.zip cpython-b409ffa848b280c1db1b4f450bfae14f263099ac.tar.gz cpython-b409ffa848b280c1db1b4f450bfae14f263099ac.tar.bz2 |
bpo-35189: Retry fnctl calls on EINTR (GH-10413)
Modify the following fnctl function to retry if interrupted by a signal
(EINTR): flock, lockf, fnctl.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/eintrdata/eintr_tester.py | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/Lib/test/eintrdata/eintr_tester.py b/Lib/test/eintrdata/eintr_tester.py index 18d9d84..c2eaf01 100644 --- a/Lib/test/eintrdata/eintr_tester.py +++ b/Lib/test/eintrdata/eintr_tester.py @@ -10,6 +10,7 @@ sub-second periodicity (contrarily to signal()). import contextlib import faulthandler +import fcntl import os import select import signal @@ -486,5 +487,43 @@ class SelectEINTRTest(EINTRBaseTest): self.assertGreaterEqual(dt, self.sleep_time) +class FNTLEINTRTest(EINTRBaseTest): + def _lock(self, lock_func, lock_name): + self.addCleanup(support.unlink, support.TESTFN) + code = '\n'.join(( + "import fcntl, time", + "with open('%s', 'wb') as f:" % support.TESTFN, + " fcntl.%s(f, fcntl.LOCK_EX)" % lock_name, + " time.sleep(%s)" % self.sleep_time)) + start_time = time.monotonic() + proc = self.subprocess(code) + with kill_on_error(proc): + with open(support.TESTFN, 'wb') as f: + while True: # synchronize the subprocess + dt = time.monotonic() - start_time + if dt > 60.0: + raise Exception("failed to sync child in %.1f sec" % dt) + try: + lock_func(f, fcntl.LOCK_EX | fcntl.LOCK_NB) + lock_func(f, fcntl.LOCK_UN) + time.sleep(0.01) + except BlockingIOError: + break + # the child locked the file just a moment ago for 'sleep_time' seconds + # that means that the lock below will block for 'sleep_time' minus some + # potential context switch delay + lock_func(f, fcntl.LOCK_EX) + dt = time.monotonic() - start_time + self.assertGreaterEqual(dt, self.sleep_time) + self.stop_alarm() + proc.wait() + + def test_lockf(self): + self._lock(fcntl.lockf, "lockf") + + def test_flock(self): + self._lock(fcntl.flock, "flock") + + if __name__ == "__main__": unittest.main() |