vscode-cpptools icon indicating copy to clipboard operation
vscode-cpptools copied to clipboard

getRemoteProcessesExtendedRemote() sensitive to gdb warnings

Open williamjenagility opened this issue 6 months ago • 1 comments

Environment

  • OS and version: Ubuntu 24.04 LTS
  • VS Code:
Version: 1.100.3
Commit: 258e40fedc6cb8edf399a463ce3a9d32e7e1f6f3
Date: 2025-06-02T13:30:54.273Z
Electron: 34.5.1
ElectronBuildId: 11369351
Chromium: 132.0.6834.210
Node.js: 20.19.0
V8: 13.2.152.41-electron.0
OS: Linux x64 6.8.0-60-generic snap
  • C/C++ extension: 1.25.3
  • OS and version of remote machine (if applicable):
  • GDB / LLDB version:
$ gdb --version
GNU gdb (Ubuntu 15.0.50.20240403-0ubuntu1) 15.0.50.20240403-git
Copyright (C) 2024 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Bug Summary and Steps to Reproduce

Bug Summary:

I am attempting to attach to a gdbserver instance from vscode. My process looks something like this:

  1. Start debugger which kicks off a task that launches a gdbserver instance. I am using bazel run --run_under='gdbserver :14000 so it is not possible for me to have vscode launch gdbserver on a binary directly.
  2. vscode will call gdb -ex "target extended-remote :14000" -ex "info os processes" -batch to get the remote processes
  3. gdb will output a warning like warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead. to stderr. This is not an error - the actual gdb invocation for debugging will have the set sysroot / call.
  4. https://github.com/microsoft/vscode-cpptools/blob/3fc041daf68b871bd147ab89b8049111bfedd00c/Extension/src/Debugger/attachToProcess.ts#L199 sees len(stderr) !== 0 and considers the remote process query a failure.

As said above, this warning is okay. I'm not sure what the best way to fix this is.

Debugger Configurations

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "bazel-run-gdbserver",
      "type": "shell",
      "command": "bazel run -c dbg --run_under='gdbserver :14000' ${input:pickBazelTarget}",
      "options": {
        "cwd": "${workspaceFolder}"
      },
      "isBackground": true,
      "problemMatcher": {
        "background": {
          "activeOnStart": true,
          "beginsPattern": "^exec ${PAGER:-/usr/bin/less}.*",
          "endsPattern": "^Listening on port.*",
        },
        "pattern": {
          "regexp": "",
        }
      }
    }
  ],
  "inputs": [
    {
      "id": "pickBazelTarget",
      "type": "command",
      "command": "bazel.pickTarget",
      "args": {
        "query": "kind('cc_binary|cc_test', //...:*)",
        "placeHolder": "Select Bazel target",
      }
    },
  ]
}

launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Bazel Target (Attach)",
      "type": "cppdbg",
      "request": "attach",
      "program": "dummy_binary", // not important, we're not reading symbols from this anyway
      "MIMode": "gdb",
      "useExtendedRemote": true,
      "miDebuggerServerAddress": ":14000",
      "miDebuggerPath": "gdb",
      "setupCommands": [
        {
          "description": "Set local sysroot",
          "text": "set sysroot /",
          "ignoreFailures": true
        },
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        },
        {
          "description": "Enable break on all exceptions",
          "text": "catch throw",
          "ignoreFailures": true
        },
        {
          "description": "Set search directory",
          "text": "dir ${workspaceFolder}",
          "ignoreFailures": true
        },
        {
          "description": "bazel-out -> bazel/out",
          "text": "set substitute-path bazel-out bazel/out",
          "ignoreFailures": true
        },
      ],
      "preLaunchTask": "bazel-run-gdbserver",
    }
  ]
}

Debugger Logs

N/A

Other Extensions

BazelBuild.vscode-bazel 0.11.0. Extension is used to help launch the helper task.

Additional Information

No response

williamjenagility avatar Jun 05 '25 21:06 williamjenagility

Hi williamjenagility ,

Thanks for your work on this project! I’ve looked into the issue where getRemoteProcessesExtendedRemote() treats GDB warnings (like "File transfers from remote targets can be slow...") as errors.

I’ve implemented a fix that:

Identifies and ignores known non-critical stderr warnings from GDB

Ensures only unexpected or critical errors cause failure

Keeps the process list parsing logic intact

This should make the remote attach process more reliable, especially in setups where set sysroot is handled elsewhere.

Let me know if you'd like changes or improvements — happy to help!

Best, James

private async getRemoteProcessesExtendedRemote(miDebuggerPath: string, miDebuggerServerAddress: string): Promise<AttachItem[]> { const args: string[] = [-ex, target extended-remote ${miDebuggerServerAddress}, -ex, info os processes, -batch`]; let processListOutput: util.ProcessReturnType = await util.spawnChildProcess(miDebuggerPath, args);

// Retry logic in case the device isn't responsive right away
for (let i: number = 0; i < 5 && !processListOutput.succeeded && processListOutput.outputError.length === 0; i++) {
    processListOutput = await util.spawnChildProcess(miDebuggerPath, args);
}

// Handle critical connection failures
if (!processListOutput.succeeded) {
    throw new Error(localize('failed.to.make.gdb.connection', 'Failed to make GDB connection: "{0}".', processListOutput.output));
}

// List of known harmless warnings to ignore
const knownWarnings = [
    'File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.'
];

// Split and filter stderr output
const nonIgnorableErrors = processListOutput.outputError
    .split('\n')
    .map(line => line.trim())
    .filter(line => line.length > 0 && !knownWarnings.some(warning => line.includes(warning)));

if (nonIgnorableErrors.length > 0) {
    throw new Error(localize('failed.to.make.gdb.connection', 'Failed to make GDB connection: "{0}".', nonIgnorableErrors.join('\n')));
}

const processes: AttachItem[] = this.parseProcessesFromInfoOsProcesses(processListOutput.output);
if (!processes || processes.length === 0) {
    throw new Error(localize('failed.to.parse.processes', 'Failed to parse processes: "{0}".', processListOutput.output));
}
return processes;

} `

webcrafters7415 avatar Jun 08 '25 05:06 webcrafters7415

Also encountering this issue. I believe it would make the most sense to simplify the error checks and simply ignore stderr, only using it for the error message when the exit code is nonzero (succeeded is false), as 0 exit code should always be taken to mean that the command executed successfully.

Something like

private async getRemoteProcessesExtendedRemote(miDebuggerPath: string, miDebuggerServerAddress: string): Promise<AttachItem[]> {
    const args: string[] = [`-ex "target extended-remote ${miDebuggerServerAddress}"`, '-ex "info os processes"', '-batch'];
    let processListOutput: util.ProcessReturnType = await util.spawnChildProcess(miDebuggerPath, args);
    // The device may not be responsive for a while during the restart after image deploy. Retry 5 times.
    for (let i: number = 0; i < 5 && !processListOutput.succeeded; i++) {
        processListOutput = await util.spawnChildProcess(miDebuggerPath, args);
    }

    if (!processListOutput.succeeded) {
        throw new Error(localize('failed.to.make.gdb.connection', 'Failed to make GDB connection: {0}.', processListOutput.output));
    }

    const processes: AttachItem[] = this.parseProcessesFromInfoOsProcesses(processListOutput.output);
    if (!processes || processes.length === 0) {
        throw new Error(localize('failed.to.parse.processes', 'Failed to parse processes: "{0}".', processListOutput.output));
    }
    return processes;
}

Would something like this be suitable @sean-mcmanus? I can submit a PR

KKhanhH avatar Aug 05 '25 21:08 KKhanhH