Skip to content

Commit d032c59

Browse files
committed
tests: Retry container process check during teardown
I'm about 75% sure the check is an unavoidable race condition, see #694 (comment). If it occurs again, then reopen the issue. Fixes #694
1 parent 3152042 commit d032c59

File tree

2 files changed

+30
-6
lines changed

2 files changed

+30
-6
lines changed

docs/changelog.rst

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ Unreleased
2929
* :gh:issue:`905` Initial support for templated ``ansible_ssh_args``,
3030
``ansible_ssh_common_args``, and ``ansible_ssh_extra_args`` variables.
3131
NB: play or task scoped variables will probably still fail.
32+
* :gh:issue:`694` CI: Fixed a race condition and some resource leaks causing
33+
some of intermittent failures when running the test suite.
3234

3335

3436
v0.3.9 (2024-08-13)

tests/testlib.py

+28-6
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,17 @@ def data_path(suffix):
146146
return path
147147

148148

149+
def retry(fn, on, max_attempts, delay):
150+
for i in range(max_attempts):
151+
try:
152+
return fn()
153+
except on:
154+
if i >= max_attempts - 1:
155+
raise
156+
else:
157+
time.sleep(delay)
158+
159+
149160
def threading__thread_is_alive(thread):
150161
"""Return whether the thread is alive (Python version compatibility shim).
151162
@@ -562,18 +573,24 @@ def wait_for_sshd(self):
562573
wait_for_port(self.get_host(), self.port, pattern='OpenSSH')
563574

564575
def check_processes(self):
565-
args = ['docker', 'exec', self.container_name, 'ps', '-o', 'comm=']
576+
# Get Accounting name (ucomm) & command line (args) of each process
577+
# in the container. No truncation (-ww). No column headers (foo=).
578+
ps_output = subprocess.check_output([
579+
'docker', 'exec', self.container_name,
580+
'ps', '-w', '-w', '-o', 'ucomm=', '-o', 'args=',
581+
])
582+
ps_lines = ps_output.decode().splitlines()
583+
processes = [tuple(line.split(None, 1)) for line in ps_lines]
566584
counts = {}
567-
for comm in subprocess.check_output(args).decode().splitlines():
568-
comm = comm.strip()
569-
counts[comm] = counts.get(comm, 0) + 1
585+
for ucomm, _ in processes:
586+
counts[ucomm] = counts.get(ucomm, 0) + 1
570587

571588
if counts != {'ps': 1, 'sshd': 1}:
572589
assert 0, (
573590
'Docker container %r contained extra running processes '
574591
'after test completed: %r' % (
575592
self.container_name,
576-
counts
593+
processes,
577594
)
578595
)
579596

@@ -630,7 +647,12 @@ def setUpClass(cls):
630647

631648
@classmethod
632649
def tearDownClass(cls):
633-
cls.dockerized_ssh.check_processes()
650+
retry(
651+
cls.dockerized_ssh.check_processes,
652+
on=AssertionError,
653+
max_attempts=5,
654+
delay=0.1,
655+
)
634656
cls.dockerized_ssh.close()
635657
super(DockerMixin, cls).tearDownClass()
636658

0 commit comments

Comments
 (0)