From: Adrian Freihofer <[email protected]>

Have GDB ONCE and ATTACH target commands wait for the listening socket,
report a generated readiness marker, and remain active for the debug
session. Make the VS Code background-task matcher wait for that marker
instead of accepting arbitrary output.

Centralize TCP readiness checks, timeout cleanup, server names, and
marker generation in DebuggerCrossConfig. Reuse the TCP wait for
persistent GDB and LLDB servers, and reject the unused LLDB one-shot
mode explicitly.

Signed-off-by: Adrian Freihofer <[email protected]>
---
 meta/lib/oeqa/selftest/cases/devtool.py     |  7 ++--
 scripts/lib/devtool/ide_plugins/__init__.py | 41 ++++++++++++++-------
 scripts/lib/devtool/ide_plugins/ide_code.py |  7 +++-
 3 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/meta/lib/oeqa/selftest/cases/devtool.py 
b/meta/lib/oeqa/selftest/cases/devtool.py
index d84a18e8b6..04a42b8906 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -3508,10 +3508,11 @@ class DevtoolIdeSdkTests(DevtoolBase):
 
         # Start gdbserver on target using the task command (keep the ssh 
connection open while debugging)
         ssh_gdbserver_cmd = [task_command] + task_args
-        # Fix shell command escaping - remove extra quotes from the last 
argument
-        # The task_args likely contains a quoted shell command that needs to 
be unquoted
+        # The tasks.json argument is formatted for an intermediate shell. Strip
+        # its quotes and restore dollar expansions before passing it directly 
to
+        # SSH via subprocess.
         if len(ssh_gdbserver_cmd) > 0 and 
ssh_gdbserver_cmd[-1].startswith('"') and ssh_gdbserver_cmd[-1].endswith('"'):
-            ssh_gdbserver_cmd[-1] = ssh_gdbserver_cmd[-1][1:-1]  # Remove 
surrounding quotes
+            ssh_gdbserver_cmd[-1] = ssh_gdbserver_cmd[-1][1:-1].replace('\\$', 
'$')
         self.logger.debug(f"Starting gdbserver with command: {' 
'.join(ssh_gdbserver_cmd)}")
         with RunCmdBackground(ssh_gdbserver_cmd, output_log=self._cmd_logger):
             # Give gdbserver a moment to start
diff --git a/scripts/lib/devtool/ide_plugins/__init__.py 
b/scripts/lib/devtool/ide_plugins/__init__.py
index deb6050907..6c88e0e34e 100644
--- a/scripts/lib/devtool/ide_plugins/__init__.py
+++ b/scripts/lib/devtool/ide_plugins/__init__.py
@@ -101,6 +101,12 @@ class DebuggerCrossConfig:
         hex_port = "%04X" % self.debug_server_port
         return "grep -q :%s /proc/net/tcp /proc/net/tcp6 2>/dev/null" % 
hex_port
 
+    def get_debug_server_ready_marker(self, port):
+        return "%s ready on port %s" % (self.DEBUG_SERVER_NAME, port)
+
+    def get_debug_server_ready_marker_pattern(self):
+        return "^%s$" % self.get_debug_server_ready_marker("[0-9]+")
+
     def _target_wait_for_tcp_port_cmd(self, pid_var=None):
         cleanup = ""
         if pid_var:
@@ -130,6 +136,7 @@ class GdbCrossConfig(DebuggerCrossConfig):
     gdbinit / gdb wrapper scripts used by ide=none as well as the
     target-side tmp/pid/log paths consumed by the gdbserver start command.
     """
+    DEBUG_SERVER_NAME = "gdbserver"
 
     def __init__(self, image_recipe, modified_recipe, binary,
                  default_mode=DebuggerServerModes.MULTI):
@@ -172,26 +179,35 @@ class GdbCrossConfig(DebuggerCrossConfig):
           "\"/bin/sh -c '/usr/bin/gdbserver --once :1234 
/usr/bin/cmake-example'\""
         """
         if server_mode == DebuggerServerModes.ONCE:
-            gdbserver_cmd_start = "%s --once :%s %s" % (
+            gdbserver_cmd_start = "%s --once :%s %s & " % (
                 self.debugger_cross.debug_server_path, self.debug_server_port, 
self.binary.binary_path)
+            gdbserver_cmd_start += "_gdbserver_pid=\\$!; "
+            gdbserver_cmd_start += self._target_wait_for_tcp_port_cmd(
+                "gdbserver_pid") + " "
+            gdbserver_cmd_start += "echo %s; wait \\$_gdbserver_pid" % (
+                self.get_debug_server_ready_marker(self.debug_server_port))
         elif server_mode == DebuggerServerModes.ATTACH:
             pid_command = self.binary.pid_command
             if pid_command:
-                gdbserver_cmd_start = "%s --attach :%s \\$(%s)" % (
+                gdbserver_cmd_start = "%s --attach :%s \\$(%s) & " % (
                     self.debugger_cross.debug_server_path,
                     self.debug_server_port,
                     pid_command)
+                gdbserver_cmd_start += "_gdbserver_pid=\\$!; "
+                gdbserver_cmd_start += self._target_wait_for_tcp_port_cmd(
+                    "gdbserver_pid") + " "
+                gdbserver_cmd_start += "echo %s; wait \\$_gdbserver_pid" % (
+                    self.get_debug_server_ready_marker(self.debug_server_port))
             else:
                 raise DevtoolError("Cannot use gdbserver attach mode for 
binary %s. No PID found." % self.binary.binary_path)
         elif server_mode == DebuggerServerModes.MULTI:
-            hex_port = "%04X" % self.debug_server_port
-            gdbserver_cmd_start = "grep -q :%s /proc/net/tcp /proc/net/tcp6 
2>/dev/null && exit 0; " % hex_port
+            gdbserver_cmd_start = self._target_tcp_port_check_cmd() + " && 
exit 0; "
             gdbserver_cmd_start += "mkdir -p %s; " % 
self._gdbserver_tmp_dir(server_mode)
-            gdbserver_cmd_start += "%s --multi :%s > %s 2>&1 & " % (
+            gdbserver_cmd_start += "%s --multi :%s > %s 2>&1 & 
_gdbserver_pid=\\$!; " % (
                 self.debugger_cross.debug_server_path, self.debug_server_port, 
self._gdbserver_log_file(server_mode))
-            gdbserver_cmd_start += "echo \\$! > %s; " % 
self._gdbserver_pid_file(server_mode)
-            gdbserver_cmd_start += "_w=0; while ! grep -q :%s /proc/net/tcp 
/proc/net/tcp6 2>/dev/null; " % hex_port
-            gdbserver_cmd_start += "do _w=\\$((_w+1)); [ \\$_w -lt 100 ] || 
exit 1; sleep 0.1; done;"
+            gdbserver_cmd_start += "echo \\$_gdbserver_pid > %s; " % 
self._gdbserver_pid_file(server_mode)
+            gdbserver_cmd_start += self._target_wait_for_tcp_port_cmd(
+                "gdbserver_pid")
         else:
             raise DevtoolError("Unsupported gdbserver mode: %s" % server_mode)
         return "\"/bin/sh -c '" + gdbserver_cmd_start + "'\""
@@ -235,10 +251,7 @@ class LldbServerConfig(DebuggerCrossConfig):
         # lldb-server 21.x and the remote lldb client connects from the host.
         # Start from /tmp because lldb-server creates temp files in its cwd and
         # the SSH default cwd (/home/root) may not exist on a minimal image.
-        if mode == DebuggerServerModes.ONCE:
-            cmd = "cd /tmp && %s platform --one-shot --server --listen *:%s" % 
(
-                lldb_server, self.debug_server_port)
-        elif mode == DebuggerServerModes.MULTI:
+        if mode == DebuggerServerModes.MULTI:
             pid_file = self._lldb_server_pid_file(mode)
             tmp_dir = self._lldb_server_tmp_dir(mode)
             log_file = self._lldb_server_log_file(mode)
@@ -252,8 +265,8 @@ class LldbServerConfig(DebuggerCrossConfig):
                 "lldb_server_pid")
         else:
             raise DevtoolError(
-                "lldb-server does not support mode %s "
-                "(ATTACH is handled client-side with 'process attach')" % mode)
+                "lldb-server only supports MULTI mode; "
+                "ATTACH is handled client-side with 'process attach': %s" % 
mode)
         return "\"/bin/sh -c '" + cmd + "'\""
 
     def _target_kill_cmd(self):
diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py 
b/scripts/lib/devtool/ide_plugins/ide_code.py
index 9faba3f2d1..5b66c56e35 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -609,6 +609,11 @@ class IdeVSCode(IdeBase):
                     # ONCE / ATTACH: gdbserver runs in the foreground for the
                     # whole session, so VSCode needs isBackground + a pattern
                     # matcher to avoid waiting for the task to exit.
+                    if server_mode in (DebuggerServerModes.ONCE,
+                                       DebuggerServerModes.ATTACH):
+                        ends_pattern = 
cross_debug_config.get_debug_server_ready_marker_pattern()
+                    else:
+                        ends_pattern = "."
                     new_task = {
                         "label": 
cross_debug_config.id_pretty_mode(server_mode),
                         "type": "shell",
@@ -628,7 +633,7 @@ class IdeVSCode(IdeBase):
                                 "background": {
                                     "activeOnStart": True,
                                     "beginsPattern": ".",
-                                    "endsPattern": ".",
+                                    "endsPattern": ends_pattern,
                                 }
                             }
                         ]
-- 
2.55.0

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#243066): 
https://lists.openembedded.org/g/openembedded-core/message/243066
Mute This Topic: https://lists.openembedded.org/mt/120667689/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to