From 334b6e0cdbe1b80b14413548016e6b0430d6173c Mon Sep 17 00:00:00 2001 From: Devershi Purohit Date: Mon, 5 Oct 2026 19:29:25 +0530 Subject: [PATCH 1/3] MOB-43620 Start Xvfb with -noreset to stop the 56-iteration Chrome hang Root cause of BPT tests failing on exactly iteration 56 with "DevToolsActivePort file doesn't exist" when an engine runs 1 user: - pyvirtualdisplay starts Xvfb with stderr=PIPE and only reads it at stop() (communicate()). - With 1 user, Chrome quits before the next starts, so Xvfb hits zero clients and resets after every iteration. - On Ubuntu 24.04 (xkb-data 2.41) every reset makes xkbcomp write ~1174 B of "Could not resolve keysym" warnings to that stderr. - After ~56 resets the 64 KiB pipe is full, xkbcomp blocks on write, Xvfb waits on xkbcomp forever and stops accepting connections; every later Chrome launch hangs at X11 init and times out after 60s. Reproduced without Chrome on ubuntu:24.04 Xvfb 21.1.12: X connection #56 hangs with xkbcomp in do_wait. With -noreset, 300 connections OK. Matches cloud atop (stuck xkbcomp at the first failure) and why runs with >=2 users per engine (overlapping Chromes, no resets) never fail. Co-Authored-By: Claude Opus 5.5 --- bzt/modules/services.py | 4 +++- tests/unit/modules/test_services.py | 35 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/bzt/modules/services.py b/bzt/modules/services.py index 153fe1612e..68b5af307b 100644 --- a/bzt/modules/services.py +++ b/bzt/modules/services.py @@ -531,7 +531,9 @@ def set_virtual_display(self): else: width = self.parameters.get("width", 1024) height = self.parameters.get("height", 768) - self.virtual_display = Display(size=(width, height)) + # -noreset: each reset writes xkbcomp warnings to Xvfb's unread stderr pipe; + # after ~55 resets the pipe fills and Xvfb hangs (MOB-43620) + self.virtual_display = Display(size=(width, height), extra_args=["-noreset"]) self.virtual_display.start() msg = "Starting virtual display[%s] %s" self.log.info(msg, (width, height), self.virtual_display.new_display_var) diff --git a/tests/unit/modules/test_services.py b/tests/unit/modules/test_services.py index a4e0212468..f44dfb6bda 100644 --- a/tests/unit/modules/test_services.py +++ b/tests/unit/modules/test_services.py @@ -471,3 +471,38 @@ def test_jmeter_rampup_benshell_ports(self): self.log_recorder.info_buff.getvalue()) finally: self.engine.provisioning.executors = executors + + +class TestVirtualDisplay(BZTestCase): + def test_xvfb_started_with_noreset(self): + calls = [] + + class DisplayMock(object): + new_display_var = ":99" + + def __init__(self, **kwargs): + calls.append(kwargs) + + def start(self): + os.environ["DISPLAY"] = self.new_display_var + + orig_display, orig_is_windows = bzt.modules.services.Display, bzt.modules.services.is_windows + old_env = os.environ.get("DISPLAY") + try: + bzt.modules.services.Display = DisplayMock + bzt.modules.services.is_windows = lambda: False + bzt.modules.services.VirtualDisplay.SHARED_VIRTUAL_DISPLAY = None + obj = bzt.modules.services.VirtualDisplay() + obj.engine = EngineEmul() + obj.set_virtual_display() + finally: + bzt.modules.services.Display, bzt.modules.services.is_windows = orig_display, orig_is_windows + bzt.modules.services.VirtualDisplay.SHARED_VIRTUAL_DISPLAY = None + if old_env is None: + os.environ.pop("DISPLAY", None) + else: + os.environ["DISPLAY"] = old_env + + self.assertEqual(1, len(calls)) + self.assertEqual((1024, 768), calls[0]["size"]) + self.assertIn("-noreset", calls[0]["extra_args"]) From 759ec789115428b3fad721297e93afeb0fd27e31 Mon Sep 17 00:00:00 2001 From: Devershi Purohit Date: Mon, 5 Oct 2026 20:17:07 +0530 Subject: [PATCH 2/3] MOB-43620 Add changes note for Xvfb -noreset fix Co-Authored-By: Claude Opus 5.5 --- site/dat/docs/changes/fix-xvfb-noreset.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 site/dat/docs/changes/fix-xvfb-noreset.change diff --git a/site/dat/docs/changes/fix-xvfb-noreset.change b/site/dat/docs/changes/fix-xvfb-noreset.change new file mode 100644 index 0000000000..f6082a39af --- /dev/null +++ b/site/dat/docs/changes/fix-xvfb-noreset.change @@ -0,0 +1 @@ +Fixed Selenium tests with 1 user per engine failing from iteration 56 on (Chrome "DevToolsActivePort file doesn't exist"): virtual display (Xvfb) now starts with `-noreset`. \ No newline at end of file From f3b6a15ecb4f5c48bbfae9ab89d3f0e0f43a286a Mon Sep 17 00:00:00 2001 From: Devershi Purohit Date: Mon, 5 Oct 2026 20:20:05 +0530 Subject: [PATCH 3/3] MOB-43620 Remove changes note Co-Authored-By: Claude Opus 5.5 --- site/dat/docs/changes/fix-xvfb-noreset.change | 1 - 1 file changed, 1 deletion(-) delete mode 100644 site/dat/docs/changes/fix-xvfb-noreset.change diff --git a/site/dat/docs/changes/fix-xvfb-noreset.change b/site/dat/docs/changes/fix-xvfb-noreset.change deleted file mode 100644 index f6082a39af..0000000000 --- a/site/dat/docs/changes/fix-xvfb-noreset.change +++ /dev/null @@ -1 +0,0 @@ -Fixed Selenium tests with 1 user per engine failing from iteration 56 on (Chrome "DevToolsActivePort file doesn't exist"): virtual display (Xvfb) now starts with `-noreset`. \ No newline at end of file