https://github.com/charles-zablit updated https://github.com/llvm/llvm-project/pull/172879
>From 85f80882a497ad071b33c4efbc638226edd9a6b3 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Thu, 18 Dec 2025 16:59:34 +0000 Subject: [PATCH 1/2] [lldb-dap] refactor monitor thread in tests --- .../tools/lldb-dap/attach/TestDAP_attach.py | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py index d6287397a93b0..7d1b3750a04a2 100644 --- a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py +++ b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py @@ -16,7 +16,7 @@ @skipIf(oslist=["linux"], archs=["arm$"]) class TestDAP_attach(lldbdap_testcase.DAPTestCaseBase): def spawn(self, args): - self.process = subprocess.Popen( + self.target_process = subprocess.Popen( args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, @@ -27,12 +27,17 @@ def spawn(self, args): def spawn_and_wait(self, program, delay): time.sleep(delay) self.spawn([program]) - self.process.wait() + proc = self.target_process + # Wait for either the process to exit or the event to be set + while proc.poll() is None and not self.spawn_event.is_set(): + time.sleep(0.1) + proc.kill() + proc.wait() def continue_and_verify_pid(self): self.do_continue() - out, _ = self.process.communicate("foo") - self.assertIn(f"pid = {self.process.pid}", out) + out, _ = self.target_process.communicate("foo") + self.assertIn(f"pid = {self.target_process.pid}", out) def test_by_pid(self): """ @@ -40,7 +45,7 @@ def test_by_pid(self): """ program = self.build_and_create_debug_adapter_for_attach() self.spawn([program]) - self.attach(pid=self.process.pid) + self.attach(pid=self.target_process.pid) self.continue_and_verify_pid() def test_by_name(self): @@ -65,6 +70,7 @@ def test_by_name_waitFor(self): doesn't exist yet. """ program = self.build_and_create_debug_adapter_for_attach() + self.spawn_event = threading.Event() self.spawn_thread = threading.Thread( target=self.spawn_and_wait, args=( @@ -73,8 +79,13 @@ def test_by_name_waitFor(self): ), ) self.spawn_thread.start() - self.attach(program=program, waitFor=True) - self.continue_and_verify_pid() + try: + self.attach(program=program, waitFor=True) + self.continue_and_verify_pid() + finally: + self.spawn_event.set() + if self.spawn_thread.is_alive(): + self.spawn_thread.join(timeout=10) def test_attach_with_missing_debuggerId_or_targetId(self): """ >From 912ec85e8d8002cbf2dcbc7f0fe79c276a2db5a3 Mon Sep 17 00:00:00 2001 From: Charles Zablit <[email protected]> Date: Fri, 19 Dec 2025 11:35:31 +0000 Subject: [PATCH 2/2] address comments --- .../Python/lldbsuite/test/lldbtest.py | 28 +++++++++++++++---- .../tools/lldb-dap/attach/TestDAP_attach.py | 24 ++++++++-------- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 8c1eea97620e2..321320910db02 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbtest.py +++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py @@ -42,6 +42,7 @@ import sys import time import traceback +from typing import Optional, Union # Third-party modules import unittest @@ -410,17 +411,22 @@ def __init__(self, trace_on): def pid(self): return self._proc.pid - def launch(self, executable, args, extra_env): + def launch(self, executable, args, extra_env, **kwargs): env = None if extra_env: env = dict(os.environ) env.update([kv.split("=", 1) for kv in extra_env]) + stdout = kwargs.pop("stdout", DEVNULL if not self._trace_on else None) + stderr = kwargs.pop("stderr", None) + self._proc = Popen( [executable] + args, - stdout=DEVNULL if not self._trace_on else None, + stdout=stdout, + stderr=stderr, stdin=PIPE, env=env, + **kwargs, ) def terminate(self): @@ -444,6 +450,11 @@ def terminate(self): self._proc.kill() time.sleep(self._delayafterterminate) + def communicate( + self, input: Optional[str] = None, timeout: Optional[float] = None + ) -> tuple[bytes, bytes]: + return self._proc.communicate(input, timeout) + def poll(self): return self._proc.poll() @@ -460,7 +471,7 @@ def __init__(self, install_remote): def pid(self): return self._pid - def launch(self, executable, args, extra_env): + def launch(self, executable, args, extra_env, **kwargs): if self._install_remote: src_path = executable dst_path = lldbutil.join_remote_paths( @@ -943,16 +954,23 @@ def cleanupSubprocesses(self): del p del self.subprocesses[:] - def spawnSubprocess(self, executable, args=[], extra_env=None, install_remote=True): + @property + def lastSubprocess(self) -> Optional[Union[_RemoteProcess, _LocalProcess]]: + return self.subprocesses[-1] if len(self.subprocesses) > 0 else None + + def spawnSubprocess( + self, executable, args=None, extra_env=None, install_remote=True, **kwargs + ): """Creates a subprocess.Popen object with the specified executable and arguments, saves it in self.subprocesses, and returns the object. """ + args = [] if args is None else args proc = ( _RemoteProcess(install_remote) if lldb.remote_platform else _LocalProcess(self.TraceOn()) ) - proc.launch(executable, args, extra_env=extra_env) + proc.launch(executable, args, extra_env=extra_env, **kwargs) self.subprocesses.append(proc) return proc diff --git a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py index 7d1b3750a04a2..27718d91a89d5 100644 --- a/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py +++ b/lldb/test/API/tools/lldb-dap/attach/TestDAP_attach.py @@ -15,10 +15,10 @@ # process scheduling can cause a massive (minutes) delay during this test. @skipIf(oslist=["linux"], archs=["arm$"]) class TestDAP_attach(lldbdap_testcase.DAPTestCaseBase): - def spawn(self, args): - self.target_process = subprocess.Popen( - args, - stdin=subprocess.PIPE, + def spawn(self, program, args=None): + return self.spawnSubprocess( + executable=program, + args=args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, @@ -26,8 +26,7 @@ def spawn(self, args): def spawn_and_wait(self, program, delay): time.sleep(delay) - self.spawn([program]) - proc = self.target_process + proc = self.spawn(program=program) # Wait for either the process to exit or the event to be set while proc.poll() is None and not self.spawn_event.is_set(): time.sleep(0.1) @@ -36,16 +35,19 @@ def spawn_and_wait(self, program, delay): def continue_and_verify_pid(self): self.do_continue() - out, _ = self.target_process.communicate("foo") - self.assertIn(f"pid = {self.target_process.pid}", out) + proc = self.lastSubprocess + if proc is None: + self.fail(f"lastSubprocess is None") + out, _ = proc.communicate("foo") + self.assertIn(f"pid = {proc.pid}", out) def test_by_pid(self): """ Tests attaching to a process by process ID. """ program = self.build_and_create_debug_adapter_for_attach() - self.spawn([program]) - self.attach(pid=self.target_process.pid) + proc = self.spawn(program=program) + self.attach(pid=proc.pid) self.continue_and_verify_pid() def test_by_name(self): @@ -58,7 +60,7 @@ def test_by_name(self): pid_file_path = lldbutil.append_to_process_working_directory( self, "pid_file_%d" % (int(time.time())) ) - self.spawn([program, pid_file_path]) + self.spawn(program=program, args=[pid_file_path]) lldbutil.wait_for_file_on_target(self, pid_file_path) self.attach(program=program) _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
