Wait until process pid completes and check that the process exit code is exitcode. Raise an AssertionError if the process exit code is not equal to exitcode. If the process runs longer than timeout seconds (LONG_TIMEOUT by default), kill the process (if signal.SIGKILL is avail
(pid, *, exitcode, timeout=None)
| 2374 | |
| 2375 | |
| 2376 | def wait_process(pid, *, exitcode, timeout=None): |
| 2377 | """ |
| 2378 | Wait until process pid completes and check that the process exit code is |
| 2379 | exitcode. |
| 2380 | |
| 2381 | Raise an AssertionError if the process exit code is not equal to exitcode. |
| 2382 | |
| 2383 | If the process runs longer than timeout seconds (LONG_TIMEOUT by default), |
| 2384 | kill the process (if signal.SIGKILL is available) and raise an |
| 2385 | AssertionError. The timeout feature is not available on Windows. |
| 2386 | """ |
| 2387 | if os.name != "nt": |
| 2388 | import signal |
| 2389 | |
| 2390 | if timeout is None: |
| 2391 | timeout = LONG_TIMEOUT |
| 2392 | |
| 2393 | start_time = time.monotonic() |
| 2394 | for _ in sleeping_retry(timeout, error=False): |
| 2395 | pid2, status = os.waitpid(pid, os.WNOHANG) |
| 2396 | if pid2 != 0: |
| 2397 | break |
| 2398 | # rety: the process is still running |
| 2399 | else: |
| 2400 | try: |
| 2401 | os.kill(pid, signal.SIGKILL) |
| 2402 | os.waitpid(pid, 0) |
| 2403 | except OSError: |
| 2404 | # Ignore errors like ChildProcessError or PermissionError |
| 2405 | pass |
| 2406 | |
| 2407 | dt = time.monotonic() - start_time |
| 2408 | raise AssertionError(f"process {pid} is still running " |
| 2409 | f"after {dt:.1f} seconds") |
| 2410 | else: |
| 2411 | # Windows implementation: don't support timeout :-( |
| 2412 | pid2, status = os.waitpid(pid, 0) |
| 2413 | |
| 2414 | exitcode2 = os.waitstatus_to_exitcode(status) |
| 2415 | if exitcode2 != exitcode: |
| 2416 | raise AssertionError(f"process {pid} exited with code {exitcode2}, " |
| 2417 | f"but exit code {exitcode} is expected") |
| 2418 | |
| 2419 | # sanity check: it should not fail in practice |
| 2420 | if pid2 != pid: |
| 2421 | raise AssertionError(f"pid {pid2} != pid {pid}") |
| 2422 | |
| 2423 | def skip_if_broken_multiprocessing_synchronize(): |
| 2424 | """ |
searching dependent graphs…