Skip to content

Commit

Permalink
tests: Retry container process check during teardown
Browse files Browse the repository at this point in the history
I'm about 75% sure the check is an unavoidable race condition, see
mitogen-hq#694 (comment). If
it occurs again, then reopen the issue.

Fixes mitogen-hq#694
  • Loading branch information
moreati committed Sep 10, 2024
1 parent 3152042 commit d032c59
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Unreleased
* :gh:issue:`905` Initial support for templated ``ansible_ssh_args``,
``ansible_ssh_common_args``, and ``ansible_ssh_extra_args`` variables.
NB: play or task scoped variables will probably still fail.
* :gh:issue:`694` CI: Fixed a race condition and some resource leaks causing
some of intermittent failures when running the test suite.


v0.3.9 (2024-08-13)
Expand Down
34 changes: 28 additions & 6 deletions tests/testlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,17 @@ def data_path(suffix):
return path


def retry(fn, on, max_attempts, delay):
for i in range(max_attempts):
try:
return fn()
except on:
if i >= max_attempts - 1:
raise
else:
time.sleep(delay)


def threading__thread_is_alive(thread):
"""Return whether the thread is alive (Python version compatibility shim).
Expand Down Expand Up @@ -562,18 +573,24 @@ def wait_for_sshd(self):
wait_for_port(self.get_host(), self.port, pattern='OpenSSH')

def check_processes(self):
args = ['docker', 'exec', self.container_name, 'ps', '-o', 'comm=']
# Get Accounting name (ucomm) & command line (args) of each process
# in the container. No truncation (-ww). No column headers (foo=).
ps_output = subprocess.check_output([
'docker', 'exec', self.container_name,
'ps', '-w', '-w', '-o', 'ucomm=', '-o', 'args=',
])
ps_lines = ps_output.decode().splitlines()
processes = [tuple(line.split(None, 1)) for line in ps_lines]
counts = {}
for comm in subprocess.check_output(args).decode().splitlines():
comm = comm.strip()
counts[comm] = counts.get(comm, 0) + 1
for ucomm, _ in processes:
counts[ucomm] = counts.get(ucomm, 0) + 1

if counts != {'ps': 1, 'sshd': 1}:
assert 0, (
'Docker container %r contained extra running processes '
'after test completed: %r' % (
self.container_name,
counts
processes,
)
)

Expand Down Expand Up @@ -630,7 +647,12 @@ def setUpClass(cls):

@classmethod
def tearDownClass(cls):
cls.dockerized_ssh.check_processes()
retry(
cls.dockerized_ssh.check_processes,
on=AssertionError,
max_attempts=5,
delay=0.1,
)
cls.dockerized_ssh.close()
super(DockerMixin, cls).tearDownClass()

Expand Down

0 comments on commit d032c59

Please sign in to comment.