summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authornierob <nierob@users.noreply.github.com>2018-11-23 15:46:12 (GMT)
committerVictor Stinner <vstinner@redhat.com>2018-11-23 15:46:12 (GMT)
commitb409ffa848b280c1db1b4f450bfae14f263099ac (patch)
tree0c240c1514a28c75ad2300852712cfdc31faaf15 /Lib
parentf653fd4d950ac092719b6152e38d77c62b443125 (diff)
downloadcpython-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.py39
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()