From 28e28c5cadf93424bfad36f3cda368c0d12c35cf Mon Sep 17 00:00:00 2001 From: Christian Breunig Date: Sun, 16 Aug 2026 08:44:22 +0000 Subject: smoketest: T9218: wait for commit lock before cli_set/*_delete/*_discard cli_commit() already busy-waits for the commit lock to clear before committing, since a concurrent process can still hold it open for a moment. cli_set()/cli_delete() had no such guard, so a set/delete issued right after a commit could race against that lingering lock and fail with a generic "Set failed"/"Delete failed" ConfigSessionError. This caused the intermittent test_bgp_27_route_reflector_client failures, whose set/commit/discard loop hammers the session tightly enough to hit the race. --- smoketest/scripts/cli/base_vyostest_shim.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'smoketest/scripts/cli') diff --git a/smoketest/scripts/cli/base_vyostest_shim.py b/smoketest/scripts/cli/base_vyostest_shim.py index 9eade3e33..0553fde05 100644 --- a/smoketest/scripts/cli/base_vyostest_shim.py +++ b/smoketest/scripts/cli/base_vyostest_shim.py @@ -25,11 +25,10 @@ from typing import Type from vyos import ConfigError from vyos.configsession import ConfigSession from vyos.configsession import ConfigSessionError -from vyos.defaults import commit_lock from vyos.frrender import mgmt_daemon +from vyos.utils.commit import commit_in_progress2 from vyos.utils.process import cmdl from vyos.utils.process import process_named_running -from vyos.utils.process import run save_config = '/tmp/vyos-smoketest-save' @@ -92,29 +91,37 @@ class VyOSUnitTestSHIM: # check process health and continuity self.assertEqual(self.mgmt_daemon_pid, process_named_running(mgmt_daemon)) + @staticmethod + def _wait_for_commit_lock(): + # A concurrent commit (e.g. a previous commit asynchronous cleanup + # still finishing) keeps the commit lock held for a moment after + # control already returned to the caller. + while commit_in_progress2(): + sleep(0.250) + def cli_set(self, path, value=None): if self.debug: str = f'set {" ".join(path)} {value}' if value else f'set {" ".join(path)}' print(str) + self._wait_for_commit_lock() self._session.set(path, value) def cli_delete(self, config): if self.debug: print('del ' + ' '.join(config)) + self._wait_for_commit_lock() self._session.delete(config) def cli_discard(self): if self.debug: print('DISCARD') + self._wait_for_commit_lock() self._session.discard() def cli_commit(self): if self.debug: print('commit') - # During a commit there is a process opening commit_lock, and run() - # returns 0 - while run(f'sudo lsof -nP {commit_lock}') == 0: - sleep(0.250) + self._wait_for_commit_lock() # Return the output of commit # Necessary for testing Warning cases return self._session.commit() -- cgit v1.2.3