vscode-python: Add support to retry attaching within a specific timeout

Summary

  • Basically the debugger is launched before the preLaunch script completes. Hence the debugger fails (as the process has not started and socketserver is not listening).
  • Suggestion: Retry attaching to the socket with a default timeout period.
  • Note; This is not a bug, but a work around for the preLaunchScripts returning even before the script has actually completed (i.e. work around for docker extension issues).

Environment data

  • VS Code version: 1.38
  • Extension version: 2019.9.34911
  • OS and version: Windows 10, 1903
  • Python version: 3.7.2

Steps to reproduce:

  1. Create a Python file, e.g. myApp.py within a workspace folder
  2. Create a task in tasks.json to launch that file in PTVSD in a Docker container (see below for full tasks.json), e.g. with: docker run -dt -v C:\Users\brandonw\.vscode\extensions\ms-python.python-2019.9.34911\pythonFiles:/pydbg -v ${workspaceFolder}:/app -w /app -p 5678:5678 --entrypoint python python:alpine /pydbg/ptvsd_launcher.py --default --host 0.0.0.0 --port 5678 --wait myApp.py
  3. Set that task as the preLaunchTask for a Python remote attach launch config (see below for full launch.json)
  4. F5

Expected behaviour

Attach works if preLaunchTask is used to start a waiting debug server with ptvsd

Actual behaviour

Attach does not work. No error is shown, it appears like debugging starts and immediately stops. If you comment out the preLaunchTask in launch.json, and then manually run the task with Ctrl + Shift + P > Run Task, it will start the container. If you then F5 it attaches successfully. I’ve also tried putting a dummy task containing a 2-second sleep inbetween, and this also works. So it seems to just be a race condition.

Logs

Nothing is output in Python output window, nor in Developer Tools console window.

Workspace

.vscode/launch.json:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Remote Attach",
            "type": "python",
            "request": "attach",
            "port": 5678,
            "host": "localhost",
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "."
                }
            ],
            "preLaunchTask": "Docker start",
            "postDebugTask": "Docker remove"
        }
    ]
}

.vscode/tasks.json (note, you’ll need to change the C:\users\brandonw.…\pythonFiles:/pydbg path):

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Docker start",
            "type": "shell",
            "command": "docker run -dt -v C:\\Users\\brandonw\\.vscode\\extensions\\ms-python.python-2019.9.34911\\pythonFiles:/pydbg -v ${workspaceFolder}:/app -w /app -p 5678:5678 --name myPythonApp --entrypoint python python:alpine /pydbg/ptvsd_launcher.py --default --host 0.0.0.0 --port 5678 --wait myApp.py",
            "problemMatcher": []
        },
        {
            "label": "Docker remove",
            "type": "shell",
            "command": "docker rm -f myPythonApp"
        }
    ]
}

myApp.py:

print("Hello world!")

print("Farewell!")

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 27 (1 by maintainers)

Most upvoted comments

Hey guys! I have a different usecase, but could benefit from debugger attach retry.

I’ve got a Django app running in a docker-dompose cluster, launched with watchmedo to enable quick code reload on file changes. Watchmedo restarts the Django process completely on code change, but that also means the debugger session disconnects.

How an I configure debugger launch configuration, so that it would try to reconnect debugger session, when Django process restarts? It takes about 5-10 secs to restart Django process and relaunch ptvsd.

In my current setup, Django spins up with docker-compose up on the side, exposes ports 8000 and 8001. ptvsd is enabled in local debug mode:

# manage.py

if __name__ == "__main__":
    from django.conf import settings
    from django.core.management import execute_from_command_line

    if settings.DEBUG:
        if os.environ.get('DJANGO_SETTINGS_MODULE').split('.')[-1] == 'docker-local':
            DEBUG_PORT = 8001
            import ptvsd
            ptvsd.enable_attach(address=('0.0.0.0', DEBUG_PORT))
            print(f'VSCode debug tools attached. Listening on port {DEBUG_PORT}')

    execute_from_command_line(sys.argv)

Debugger launch configuration:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Django: Docker debug",
      "type": "python",
      "request": "attach",
      "pathMappings": [
        {
          "localRoot": "${workspaceFolder}",
          "remoteRoot": "/src"
        }
      ],
      "port": 8001,
      "host": "127.0.0.1",
      "listen": {
        "port": 8001,
        "host": "127.0.0.1",
      }
    }
  ]
}

I wonder if it would help if you could reverse the direction of the connection? i.e. from Docker to VSCode, rather than the other way around? Basically the order for the debugger bits would be:

  1. User (or extension) starts debug session.
  2. IDE waits for incoming connection from debuggee.
  3. Debuggee starts, connects to IDE at the specified port.
  4. Debugging proceeds.

It sounds like this would solve the prelaunch problem?

I haven’t looked into Java yet so I can’t speak for it, but for .NET debugging retry is already built in between vsdbg and the debug adapter. In any case our usage is primarily Node, with .NET Core and Python in second and third. No other languages come even close to these three.

Proposed solution

  • *Retry attaching to the socket with a default timeout period. Note; This is not a bug, but a work around for the preLaunchScripts returning even before the script has actually completed (i.e. work around for docker extension issues).