]> git.ipfire.org Git - thirdparty/openembedded/openembedded-core.git/commitdiff
oe-selftest: devtool ide-sdk: wait for lldb-server readiness
authorAdrian Freihofer <adrian.freihofer@siemens.com>
Sun, 9 Aug 2026 09:35:53 +0000 (11:35 +0200)
committerRichard Purdie <richard.purdie@linuxfoundation.org>
Mon, 10 Aug 2026 10:34:56 +0000 (11:34 +0100)
The generated MULTI preLaunchTask starts lldb-server on the target and waits
for its TCP port to appear before its SSH command completes. The selftest
bypassed that contract by starting SSH in the background, sleeping for one
second, and only checking that lldb-server appeared in ps. On a loaded
autobuilder this allowed lldb --batch to connect before lldb-server had bound
its listening socket.

Run the generated preLaunchTask SSH command synchronously before lldb --batch.
This follows VS Code's foreground-task behavior and leaves listener readiness
and timeout handling in _target_start_cmd(), where the server is started.

Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
meta/lib/oeqa/selftest/cases/devtool.py

index 7145755fedc8ecad9b79f054df14d1150cd45ef9..d84a18e8b69b8c61e0db7e3c22619fda5e313108 100644 (file)
@@ -4175,8 +4175,6 @@ class DevtoolIdeSdkTests(DevtoolBase):
         (see _lldb_debug_cpp_example_batch_commands), and checks that the
         expected magic string and variable values are visible.
         """
-        sshargs = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
-
         with open(os.path.join(tempdir, '.vscode', 'launch.json')) as f:
             launch_d = json.load(f)
         with open(os.path.join(tempdir, '.vscode', 'tasks.json')) as f:
@@ -4208,7 +4206,9 @@ class DevtoolIdeSdkTests(DevtoolBase):
             # to SSH via subprocess without an intermediate shell.
             ssh_cmd[-1] = ssh_cmd[-1][1:-1].replace('\\$', '$')
 
-        # Extract connection details from initCommands
+        # The generated foreground preLaunchTask does not complete until its
+        # target-side command has observed lldb-server listening.  Run it
+        # synchronously so this selftest follows the same ordering as VS Code.
         init_commands = lldb_config["initCommands"]
         connect_cmd = next((c for c in init_commands if "platform connect" in c), None)
         self.assertIsNotNone(connect_cmd, "initCommands should contain a platform connect command")
@@ -4218,47 +4218,41 @@ class DevtoolIdeSdkTests(DevtoolBase):
         lldb_binary = os.path.join(lldb_native_sysroot, 'usr', 'bin', 'lldb')
         self.assertExists(lldb_binary, "lldb binary should exist in lldb-native sysroot")
 
-        with RunCmdBackground(ssh_cmd, output_log=self._cmd_logger):
-            time.sleep(1)
-
-            # Verify lldb-server is running on the target
-            r = runCmd('ssh %s root@%s ps' % (sshargs, qemu.ip),
-                       output_log=self._cmd_logger)
-            self.assertIn("lldb-server", r.output,
-                          "lldb-server should be running on target")
-
-            # Run lldb --batch: connect to platform, create target with remote-file,
-            # set a source-level breakpoint, and run.
-            # targetCreateCommands replaces the "program" field; each entry is
-            # passed as a separate -o command in batch mode.
-            target_create_commands = lldb_config.get("targetCreateCommands", [])
-            source_map = lldb_config.get("sourceMap", {})
-
-            lldb_batch = [lldb_binary, "--batch"]
-            for cmd in init_commands:
-                lldb_batch += ["-o", cmd]
-            for cmd in target_create_commands:
-                lldb_batch += ["-o", cmd]
-            if source_map:
-                # "settings set target.source-map" replaces the *entire*
-                # mapping list rather than appending to it. Issuing one
-                # "-o settings set target.source-map ..." per entry (as done
-                # previously) silently discards all but the last mapping, so
-                # LLDB ends up resolving source files (and verifying their
-                # DWARF MD5 checksum) against the wrong location, e.g. a
-                # stale rootfs-dbg copy of a devtool-modified recipe's own
-                # sources instead of the freshly edited workspace srctree.
-                # All pairs must therefore be set together in a single
-                # command, exactly like CodeLLDB itself does.
-                source_map_args = []
-                for k, v in source_map.items():
-                    v_resolved = v.replace("${workspaceFolder}", tempdir)
-                    source_map_args += [k, v_resolved]
-                lldb_batch += ["-o", "settings set target.source-map %s" % " ".join(source_map_args)]
-            lldb_batch += self._lldb_debug_cpp_example_batch_commands(tempdir)
-            r = runCmd(lldb_batch, output_log=self._cmd_logger)
-            self.assertEqual(r.status, 0, "lldb batch session failed: %s" % r.output)
-            self._lldb_debug_cpp_example_check(r.output, magic_string)
+        self.logger.debug("Starting lldb-server via SSH: %s", " ".join(ssh_cmd))
+        runCmd(ssh_cmd, output_log=self._cmd_logger)
+
+        # Run lldb --batch: connect to platform, create target with remote-file,
+        # set a source-level breakpoint, and run.
+        # targetCreateCommands replaces the "program" field; each entry is
+        # passed as a separate -o command in batch mode.
+        target_create_commands = lldb_config.get("targetCreateCommands", [])
+        source_map = lldb_config.get("sourceMap", {})
+
+        lldb_batch = [lldb_binary, "--batch"]
+        for cmd in init_commands:
+            lldb_batch += ["-o", cmd]
+        for cmd in target_create_commands:
+            lldb_batch += ["-o", cmd]
+        if source_map:
+            # "settings set target.source-map" replaces the *entire*
+            # mapping list rather than appending to it. Issuing one
+            # "-o settings set target.source-map ..." per entry (as done
+            # previously) silently discards all but the last mapping, so
+            # LLDB ends up resolving source files (and verifying their
+            # DWARF MD5 checksum) against the wrong location, e.g. a
+            # stale rootfs-dbg copy of a devtool-modified recipe's own
+            # sources instead of the freshly edited workspace srctree.
+            # All pairs must therefore be set together in a single
+            # command, exactly like CodeLLDB itself does.
+            source_map_args = []
+            for k, v in source_map.items():
+                v_resolved = v.replace("${workspaceFolder}", tempdir)
+                source_map_args += [k, v_resolved]
+            lldb_batch += ["-o", "settings set target.source-map %s" % " ".join(source_map_args)]
+        lldb_batch += self._lldb_debug_cpp_example_batch_commands(tempdir)
+        r = runCmd(lldb_batch, output_log=self._cmd_logger)
+        self.assertEqual(r.status, 0, "lldb batch session failed: %s" % r.output)
+        self._lldb_debug_cpp_example_check(r.output, magic_string)
 
     @OETestTag("runqemu")
     def test_devtool_ide_sdk_code_cmake_clang(self):