4
votes

Summary

I'm trying to debug a C++ program within a docker image (Ubuntu), while using VSCode as an IDE on my host system (OS X). After various tinkering with gdbserver and VSCode tasks, I'm now able to successfully run the debugger, but each time I launch a debugging session, VSCode hangs for 10 seconds, then reports the error message:

"The preLaunchTask 'docker gdb' cannot be tracked."

If I click through this error, I'm able to debug perfectly normally, but this 10 second wait each time I debug is massively frustrating.

Details

My Docker image is started via the following, so my source code is mounted in the 'app' directory. The security settings are ones I found elsewhere on Stack Overflow, required to allow gdbserver:

docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -it -v "$(pwd):/app" -w "/app" -p 9091:9091 {imageName} /bin/bash

And when I launch a debugging session on the host, I use this launch command, connecting local gdb to the docker gdbserver, and running a pre-launch task:

{
"version": "0.2.0",
"configurations": [
    {
        "name": "Remote unit test",
        "type": "cppdbg",
        "request": "launch",
        "program": "./tests/ConfigurationTest.cpp_TestRunner",
        "miDebuggerServerAddress": "localhost:9091",
        "args": [],
        "stopAtEntry": false,
        "cwd": "${workspaceRoot}",
        "environment": [],
        "externalConsole": true,
        "MIMode": "gdb",
        "preLaunchTask": "docker gdb"
    }
]
}

This is the definition of the pre-launch task; it uses docker exec to kill any existing gdbserver and start a new one, on the relevant executable:

{
"version": "2.0.0",
"tasks": [
    {
        "label":"docker gdb",
        "command": "docker exec {containerName} /bin/bash -c \"pkill gdbserver; gdbserver localhost:9091 ./tests/ConfigurationTest.cpp_TestRunner\"",
        "isBackground": true,
        "type": "shell"
        }
    ]
}

When I launch a debugging session, I get the following output immediately, which is expected:

Process ./tests/ConfigurationTest.cpp_TestRunner created; pid = 1167

Listening on port 9091

At this point, gdbserver is ready to go, and I'd love VSCode to start up its gdb. But instead VSCode waits for 10 seconds before popping up a dialog saying '"The preLaunchTask 'docker gdb' cannot be tracked."'. If I click 'Debug Anyway', the debugging session resumes as expected, and seems to behave fine.

What have I tried

The 10 second wait time sounds very similar to https://github.com/Microsoft/vscode/issues/37997, so I've tried using a problemMatcher with 'activeOnStart:true', as suggested there. This had no effect.

I thought that maybe the problem was that the docker exec command was running in the foreground, and VSCode was waiting for it to return, so I've tried executing docker exec with -d (detached mode, runs in the background), or just adding a '&' to the end of the docker command. Again, no effect.

Can anyone suggest what I can do to get rid of this annoying 10 second wait?

Many thanks.

2

2 Answers

6
votes

I ran into the same issue today, I was trying to run Mocha tests with a debugger and vscode was waiting for the debugger for the preLaunch task to finish, which is the opposite of what I needed - the task exposes the debugger so I need it running in the 'background' - to the point though, this config fixed it for me.

launch.json

{
    "version": "0.2.0",
    "configurations": [
    {
      "type": "node",
      "request": "attach",
      "name": "Docker: Attach to Mocha",
      "port": 5858,
      "address": "localhost",
      "localRoot": "${workspaceFolder}/server",
      "remoteRoot": "/usr/src/app/server",
      "protocol": "inspector",
      "preLaunchTask": "mocha-docker-debug"
    }
    ]
}

tasks.json

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
      {
        "label": "mocha-docker-debug",
        "type": "shell",
        "command": "docker exec up-ibe-server-node npm run test-debug",
        "group": "test",
        "isBackground": true,
        "presentation": {
          "reveal": "never"
        },
        "problemMatcher": {
          "owner": "mocha",
          "fileLocation": "relative",
          "pattern": [
            {
              "regexp": "^not\\sok\\s\\d+\\s(.*)$"
            },
            {
              "regexp": "\\s+(.*)$",
              "message": 1
            },
            {
              "regexp": "\\s+at\\s(.*):(\\d+):(\\d+)$",
              "file": 1,
              "line": 2,
              "column": 3
            }
          ],
          "background": {
              "activeOnStart": true,
              "beginsPattern":{
                  "regexp": "mocha*"
              },
              "endsPattern":{
                  "regexp": "Debugger listening*"
              }
          },
        }
      }
  ]
}

The main thing to notice here is isBackground flag, beginsPattern and endsPattern regexes, this tells the 'parent' launch task that when xxx has been printed to the console from the 'child' it is finished and vscode can get on with the actual task.

This may not be the exact problem you were having given that you're running a C++ app but I think it's for the same reasons.

0
votes

I have found a solution for me which is quite pragmatic.

I'm using the following preLaunchTask without the need of isBackground and regex patterns (to detect the begin and end of the task execution) by just starting gdbserver as background command/job combined with a little sleep:

{
            "label": "Start GDB remote debugger",
            "type": "shell",
            "options": {
                "cwd": "${workspaceRoot}/"
            },
            "presentation": {
                "echo": true,
                "reveal": "always",
                "focus": false,
                "panel": "shared",
                "revealProblems": "onProblem"
            },
            "command": "clear;./ssh.py 'cd /opt/bin/;(nohup gdbserver localhost:6666 myapp &);sleep 1'",
            "problemMatcher": []
        },

The whole gdbserver configuration can be found here

This works quite stable, even on slow connections via vpn in my experience.