https://github.com/python/cpython/commit/847c803c13093f3ec0a09188831e1a44f27894b1
commit: 847c803c13093f3ec0a09188831e1a44f27894b1
branch: 3.12
author: Miss Islington (bot) <[email protected]>
committer: colesbury <[email protected]>
date: 2024-07-10T14:54:45Z
summary:

[3.12] gh-107851: Fix spurious failures in fcntl eintr tests (GH-121556) 
(#121586)

On heavily loaded machines, the subprocess may finish its sleep before
the parent process manages to synchronize with it via a failed lock.

This leads to errors like:

  Exception: failed to sync child in 300.3 sec

Use pipes instead to mutually synchronize between parent and child.
(cherry picked from commit af9f6de6ea930b607f948f2c91a87fe4ca9d64db)

Co-authored-by: Sam Gross <[email protected]>

files:
M Lib/test/_test_eintr.py

diff --git a/Lib/test/_test_eintr.py b/Lib/test/_test_eintr.py
index 15586f15dfab30..493932d6c6d441 100644
--- a/Lib/test/_test_eintr.py
+++ b/Lib/test/_test_eintr.py
@@ -18,6 +18,7 @@
 import socket
 import subprocess
 import sys
+import textwrap
 import time
 import unittest
 
@@ -492,29 +493,31 @@ def test_devpoll(self):
         self.check_elapsed_time(dt)
 
 
-class FNTLEINTRTest(EINTRBaseTest):
+class FCNTLEINTRTest(EINTRBaseTest):
     def _lock(self, lock_func, lock_name):
         self.addCleanup(os_helper.unlink, os_helper.TESTFN)
-        code = '\n'.join((
-            "import fcntl, time",
-            "with open('%s', 'wb') as f:" % os_helper.TESTFN,
-            "   fcntl.%s(f, fcntl.LOCK_EX)" % lock_name,
-            "   time.sleep(%s)" % self.sleep_time))
-        start_time = time.monotonic()
-        proc = self.subprocess(code)
+        rd1, wr1 = os.pipe()
+        rd2, wr2 = os.pipe()
+        for fd in (rd1, wr1, rd2, wr2):
+            self.addCleanup(os.close, fd)
+        code = textwrap.dedent(f"""
+            import fcntl, os, time
+            with open('{os_helper.TESTFN}', 'wb') as f:
+                fcntl.{lock_name}(f, fcntl.LOCK_EX)
+                os.write({wr1}, b"ok")
+                _ = os.read({rd2}, 2)  # wait for parent process
+                time.sleep({self.sleep_time})
+        """)
+        proc = self.subprocess(code, pass_fds=[wr1, rd2])
         with kill_on_error(proc):
             with open(os_helper.TESTFN, 'wb') as f:
                 # synchronize the subprocess
+                ok = os.read(rd1, 2)
+                self.assertEqual(ok, b"ok")
+
+                # notify the child that the parent is ready
                 start_time = time.monotonic()
-                for _ in support.sleeping_retry(support.LONG_TIMEOUT, 
error=False):
-                    try:
-                        lock_func(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
-                        lock_func(f, fcntl.LOCK_UN)
-                    except BlockingIOError:
-                        break
-                else:
-                    dt = time.monotonic() - start_time
-                    raise Exception("failed to sync child in %.1f sec" % dt)
+                os.write(wr2, b"go")
 
                 # 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

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to