|
16 | 16 | SHORT_TIMEOUT, |
17 | 17 | reap_children, |
18 | 18 | requires_remote_subprocess_debugging, |
| 19 | + sleeping_retry, |
19 | 20 | ) |
20 | 21 |
|
21 | 22 | # Guard imports that require _remote_debugging module. |
@@ -84,29 +85,13 @@ def reader(): |
84 | 85 | return result[0] |
85 | 86 |
|
86 | 87 |
|
87 | | -def _wait_for_process_ready(proc, timeout): |
88 | | - # Wait for a subprocess to be ready using polling instead of fixed sleep. |
89 | | - # Returns True if process is ready, False if it exited or timeout. |
90 | | - deadline = time.time() + timeout |
91 | | - poll_interval = 0.01 |
92 | | - |
93 | | - while time.time() < deadline: |
94 | | - if proc.poll() is not None: |
95 | | - return False |
96 | | - |
97 | | - try: |
98 | | - if sys.platform == "linux": |
99 | | - if os.path.exists(f"/proc/{proc.pid}/exe"): |
100 | | - return True |
101 | | - else: |
102 | | - return True |
103 | | - except OSError: |
104 | | - pass |
105 | | - |
106 | | - time.sleep(poll_interval) |
107 | | - poll_interval = min(poll_interval * 2, 0.1) |
108 | | - |
109 | | - return proc.poll() is None |
| 88 | +def _wait_for_process_exec(proc, name, timeout): |
| 89 | + # Wait until a child process calls exec() to replace the forked process |
| 90 | + # executable. Raise AssertionError on timeout. |
| 91 | + for _ in sleeping_retry(timeout, max_delay=0.1): |
| 92 | + exe = os.readlink(f"/proc/{proc.pid}/exe") |
| 93 | + if os.path.basename(exe) == name: |
| 94 | + break |
110 | 95 |
|
111 | 96 |
|
112 | 97 | @unittest.skipIf( |
@@ -634,17 +619,13 @@ def test_is_python_process_non_python_subprocess(self): |
634 | 619 | """Test that a non-Python subprocess is not detected as Python.""" |
635 | 620 | # Start a non-Python subprocess (sleep command) |
636 | 621 | proc = subprocess.Popen( |
637 | | - ["sleep", "10"], |
| 622 | + ["sleep", "60"], |
638 | 623 | stdout=subprocess.DEVNULL, |
639 | 624 | stderr=subprocess.DEVNULL, |
640 | 625 | ) |
641 | 626 |
|
642 | 627 | try: |
643 | | - # Wait for process to be ready using polling |
644 | | - self.assertTrue( |
645 | | - _wait_for_process_ready(proc, SHORT_TIMEOUT), |
646 | | - f"Process {proc.pid} should be ready within {SHORT_TIMEOUT}s", |
647 | | - ) |
| 628 | + _wait_for_process_exec(proc, "sleep", SHORT_TIMEOUT) |
648 | 629 |
|
649 | 630 | self.assertFalse( |
650 | 631 | is_python_process(proc.pid), |
|
0 commit comments