|
7 | 7 | import os
|
8 | 8 | import platform
|
9 | 9 | import re
|
| 10 | +import select |
10 | 11 | import signal
|
11 | 12 | import stat
|
12 | 13 | import subprocess
|
@@ -450,16 +451,39 @@ def run_guest_cmd(ssh_connection, cmd, expected, use_json=False):
|
450 | 451 | assert stdout == expected
|
451 | 452 |
|
452 | 453 |
|
453 |
| -@retry(wait=wait_fixed(1), stop=stop_after_attempt(10), reraise=True) |
| 454 | +def get_process_pidfd(pid): |
| 455 | + """Get a pidfd file descriptor for the process with PID `pid` |
| 456 | +
|
| 457 | + Will return a pid file descriptor for the process with PID `pid` if it is |
| 458 | + still alive. If the process has already exited it will return `None`. |
| 459 | +
|
| 460 | + Any other error while calling the system call, will raise an OSError |
| 461 | + exception. |
| 462 | + """ |
| 463 | + try: |
| 464 | + pidfd = os.pidfd_open(pid) |
| 465 | + except ProcessLookupError: |
| 466 | + return None |
| 467 | + |
| 468 | + return pidfd |
| 469 | + |
| 470 | + |
454 | 471 | def wait_process_termination(p_pid):
|
455 | 472 | """Wait for a process to terminate.
|
456 | 473 |
|
457 |
| - Will return sucessfully if the process |
| 474 | + Will return successfully if the process |
458 | 475 | got indeed killed or raises an exception if the process
|
459 | 476 | is still alive after retrying several times.
|
460 | 477 | """
|
461 |
| - if psutil.pid_exists(p_pid): |
462 |
| - raise Exception(f"[{p_pid}] process is still alive") |
| 478 | + pidfd = get_process_pidfd(p_pid) |
| 479 | + |
| 480 | + # If pidfd is None the process has already terminated |
| 481 | + if pidfd is not None: |
| 482 | + epoll = select.epoll() |
| 483 | + epoll.register(pidfd, select.EPOLLIN) |
| 484 | + # This will return once the process exits |
| 485 | + epoll.poll() |
| 486 | + os.close(pidfd) |
463 | 487 |
|
464 | 488 |
|
465 | 489 | def get_firecracker_version_from_toml():
|
|
0 commit comments