Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attach to local process - launch.json experience #8384

Closed
luabud opened this issue Nov 5, 2019 · 22 comments
Closed

Attach to local process - launch.json experience #8384

luabud opened this issue Nov 5, 2019 · 22 comments
Assignees
Labels
area-debugging feature-request Request for new features or functionality

Comments

@luabud
Copy link
Member

luabud commented Nov 5, 2019

No description provided.

@luabud luabud added area-debugging needs PR feature-request Request for new features or functionality labels Nov 5, 2019
@luabud
Copy link
Member Author

luabud commented Nov 5, 2019

#1078

@luabud luabud added this to the FY20Q2 milestone Nov 19, 2019
@karthiknadig
Copy link
Member

  • Add processId to the attach request as a optional. (package.json, src\client\debugger\types.ts:IKnownAttachDebugArguments)
  • Ensure that we use DebugAdapterExecutable (instead of DebugAdapterServer for attach requests with processId) in the debug adapter descriptor for this case. Add telemetry here to tell us that user is trying to attach using pid (src\client\debugger\extension\adapter\factory.ts)
  • Updates to the tests.

@kimadeline
Copy link

kimadeline commented Nov 28, 2019

To validate:

  1. ensure prerequisites:
    a. in DebugAdapterDescriptorFactory experiment ("DebugAdapterFactory - experiment")
    b. in DebugAdapterNewPtvsd experiment ('"PtvsdWheels37 - experiment"')
    c. if building from source, run gulp installNewPtvsd, if that isn't working, do it manually (from the repo root):
    1. python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/python/new_ptvsd/no_wheels --no-cache-dir --implementation py --no-deps --upgrade ptvsd==5.0.0a8
    2. python -m pip --disable-pip-version-check install -t ./pythonFiles/lib/python/new_ptvsd/wheels --no-cache-dir --no-deps --upgrade ptvsd==5.0.0a8
  2. in a new workspace folder add "script.py" with the following code (an infinite loop):
import time

while True:
     print("Hello")
     time.sleep(1)
  1. add ".vscode/launch.json":
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Attach to Process",
            "type": "python",
            "request": "attach",
            "processId": 7499,
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "."
                }
            ]
        }
    ]
}
  1. in a terminal, run python script.py
  2. verify that "Hello" gets periodically printed in the debug console
  3. start a debug session using the "Attach to Process" config
  4. verify that it connects (e.g. no error, breakpoints work)

⚠️ If there's a debugger timeout then it's most likely a ptvsd issue. In that case (or for more info in any case), adjust the above steps as follows:

  • add "logToFile": true to the above "attach" config
  • for step 3 run with the following environment variables:
    • PTVSD_DEBUG=True
    • PTVSD_DEBUG_FILE=…/pydevd.log
    • e.g. PTVSD_DEBUG=True PTVSD_DEBUG_FILE=…/pydevd.log python script.py
  • (new) step 7: send that log file to the ptvsd team

@ericsnowcurrently
Copy link
Member

@kimadeline, at step 5 I'm getting the following error:

Failed to attach (connect ECONNREFUSED 127.0.0.1)

I was going to do the logging thing but the second bullet is unclear. Do you mean re-do step 3 but with those two environment variables set?

Also, how is ptvsd related to the script from step 1? Is step 3 supposed to run ptvsd on the script rather than the script itself?

@kimadeline
Copy link

Do you mean re-do step 3 but with those two environment variables set?

That's what I understood when I was given these instructions, @karthiknadig 🆘

Also, how is ptvsd related to the script from step 1? Is step 3 supposed to run ptvsd on the script rather than the script itself?

Step 1, 3 and 4 are not related to ptvsd, they are about starting a simple python process that ptvsd can attach to (in steps 5 and 6). You can replace steps 1, 3 and 4 with your own python process if you want.

@karthiknadig
Copy link
Member

karthiknadig commented Dec 2, 2019

For this to work, you have to be in both DebugAdapterDescriptorFactory experiment and DebugAdapterNewPtvsd experiment. If you are running from source (to control the experiment) then you should run these commands to install ptvsd, from the repo root (where the pythonFiles directory is).

python -m pip --disable-pip-version-check install -t .\pythonFiles\lib\python\new_ptvsd\no_wheels --no-cache-dir --implementation py --no-deps --upgrade ptvsd==5.0.0a8
python -m pip --disable-pip-version-check install -t .\pythonFiles\lib\python\new_ptvsd\wheels --no-cache-dir --no-deps --upgrade  ptvsd==5.0.0a8

There is a gulp task (gulp installNewPtvsd) to do this but it looks like it is not working correctly. I will make a PR to fix that. (#8871)

Do you mean re-do step 3 but with those two environment variables set?

To get the logs you have to, set the env and then start the script. and have logToFile set in launch json.

@karthiknadig
Copy link
Member

It seems to be working for me:
image

@ericsnowcurrently
Copy link
Member

Still no success. FWIW, I'm doing this over "ssh-remote" (rather than locally). However, I would not expect that to matter.

@ericsnowcurrently
Copy link
Member

FYI, I'm trying locally now.

@ericsnowcurrently
Copy link
Member

I'm getting the same "ECONNREFUSED" error locally. In case it matters, I'm on linux.

My log:

2019-12-3, 20:26:50.699 UTC                                                                                                                                                                                                                                                                                                                                   
[20:26:50.700 UTC] Started @ Tue Dec 03 2019 13:26:50 GMT-0700 (Mountain Standard Time)
[20:26:50.700 UTC] From Client:
[20:26:50.700 UTC] Content-Length: 324^M
^M
{"command":"initialize","arguments":{"clientID":"vscode","clientName":"Visual Studio Code - Insiders","adapterID":"python","pathFormat":"path","linesStartAt1":true,"columnsStartAt1":true,"supportsVariableType":true,"supportsVariablePaging":true,"supportsRunInTerminalRequest":true,"locale":"en-us"},"type":"request","seq":1}
[20:26:50.700 UTC] To Client:
[20:26:50.700 UTC] Content-Length: 761^M
^M
{"seq":1,"type":"response","request_seq":1,"command":"initialize","success":true,"body":{"supportsExceptionInfoRequest":true,"supportsConfigurationDoneRequest":true,"supportsDelayedStackTraceLoading":true,"supportsConditionalBreakpoints":true,"supportsSetVariable":true,"supportsExceptionOptions":true,"supportsGotoTargetsRequest":true,"supportsEvaluateForHovers":true,"supportsModulesRequest":true,"supportsValueFormattingOptions":true,"supportsHitConditionalBreakpoints":true,"supportsSetExpression":true,"supportsLogPoints":true,"supportTerminateDebuggee":true,"supportsCompletionsRequest":true,"exceptionBreakpointFilters":[{"filter":"raised","label":"Raised Exceptions","default":false},{"filter":"uncaught","label":"Uncaught Exceptions","default":true}]}}
[20:26:50.700 UTC] From Client:
[20:26:50.700 UTC] Content-Length: 500^M
^M
{"command":"attach","arguments":{"name":"Attach to Process","type":"python","request":"attach","processId":21881,"pathMappings":[{"localRoot":"/home/esnow/projects/work/test_projects/gh-8384","remoteRoot":"."}],"logToFile":true,"debugOptions":["RedirectOutput","UnixClient","ShowReturnValue"],"host":"localhost","justMyCode":true,"showReturnValue":true,"workspaceFolder":"<dirname>","__sessionId":"<some UUID>"},"type":"request","seq":2}
[20:26:50.701 UTC] [Error] Attach failed
[20:26:50.701 UTC] [Error] Error: connect ECONNREFUSED 127.0.0.1, Error, connect ECONNREFUSED 127.0.0.1, Error: connect ECONNREFUSED 127.0.0.1
    at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1054:14)
[20:26:50.701 UTC] To Client:
[20:26:50.701 UTC] Content-Length: 227^M
^M
{"seq":2,"type":"response","request_seq":2,"command":"attach","success":false,"message":"Failed to attach (connect ECONNREFUSED 127.0.0.1)","body":{"error":{"format":"Failed to attach (connect ECONNREFUSED 127.0.0.1)","id":1}}}
[20:26:50.703 UTC] From Client:
[20:26:50.703 UTC] Content-Length: 79^M
^M
{"command":"disconnect","arguments":{"restart":false},"type":"request","seq":3}
[20:26:50.703 UTC] onResponseDisconnect
[20:26:50.704 UTC] To Client:
[20:26:50.704 UTC] Content-Length: 81^M
^M
{"seq":3,"type":"response","request_seq":3,"command":"disconnect","success":true}
[20:26:50.705 UTC] check and shutdown

@ericsnowcurrently
Copy link
Member

@karthiknadig Out of curiosity, how does ptvsd inject itself into a running process? I haven't misunderstood the feature right? This is different from the old way of manually invoking ptvsd in the script, right?

@karthiknadig
Copy link
Member

@ericsnowcurrently these are the steps it takes:

  1. VSC starts the python debug adapter
  2. Debug adapter receives the attach request with the pid.
  3. Debug adapter starts the injector process that injects the debugger into the given process, then exits.
  4. The adapter then waits and listens to a connection from the injected debugger.
  5. After connection is received, debug adapter resumes communication with VSC, essentailly telling it that it is ready to debug.

@int19h /cc

@ericsnowcurrently
Copy link
Member

Hmm, looks like I forgot to force the experiments when I moved over to local. Trying again...

@ericsnowcurrently
Copy link
Member

Still no success. :(

From the console log:

  ERR timeout after 500 ms: Error: timeout after 500 ms
    at t.RawDebugSession.handleErrorResponse (file:///usr/share/code-insiders/resources/app/out/vs/workbench/workbench.desktop.main.js:2820:819)
    at file:///usr/share/code-insiders/resources/app/out/vs/workbench/workbench.desktop.main.js:2820:250
    at async t.RawDebugSession.shutdown (file:///usr/share/code-insiders/resources/app/out/vs/workbench/workbench.desktop.main.js:2818:336)

@int19h
Copy link

int19h commented Dec 3, 2019

It's using gdb to inject a stub that loads pydevd and ptvsd into the process.

This means that there are some magic incantations that need to be done on Linux to allow gdb to do this:
https://www.jetbrains.com/help/pycharm/attaching-to-local-process.html#prereq-ubuntu

(we'll need to reflect the same in our docs)

@ericsnowcurrently
Copy link
Member

I'm guessing that VS Code is kind enough to generate some logs files for me...

debugger.vscode_21e6c76c-ddd8-4104-8101-211da45ed975.log:

0 Starting Session:
{
    "name": "Attach to Process",
    "type": "python",
    "request": "attach",
    "processId": 29160,
    "pathMappings": [
        {
            "localRoot": "/home/esnow/projects/work/test_projects/gh-8384",
            "remoteRoot": "."
        }
    ],
    "logToFile": true,
    "debugOptions": [
        "RedirectOutput",
        "UnixClient",
        "ShowReturnValue"
    ],
    "host": "localhost",
    "justMyCode": true,
    "showReturnValue": true,
    "workspaceFolder": "/home/esnow/projects/work/test_projects/gh-8384"
}
18 Client --> Adapter:
{
    "command": "initialize",
    "arguments": {
        "clientID": "vscode",
        "clientName": "Visual Studio Code - Insiders",
        "adapterID": "python",
        "pathFormat": "path",
        "linesStartAt1": true,
        "columnsStartAt1": true,
        "supportsVariableType": true,
        "supportsVariablePaging": true,
        "supportsRunInTerminalRequest": true,
        "locale": "en-us"
    },
    "type": "request",
    "seq": 1
}
28 Exit:
Exit-Code: 2
Signal: none
28 Error:
{}
30 Client --> Adapter:
{
    "command": "disconnect",
    "arguments": {
        "restart": false
    },
    "type": "request",
    "seq": 2
}
31 Error:
{}
1033 Stopping Session

debugger.vscode_d6895110-81ae-4c81-ad3d-0168b434c883.log:

0 Starting Session:
{
    "name": "Attach to Process",
    "type": "python",
    "request": "attach",
    "processId": 29160,
    "pathMappings": [
        {
            "localRoot": "/home/esnow/projects/work/test_projects/gh-8384",
            "remoteRoot": "."
        }
    ],
    "logToFile": true,
    "debugOptions": [
        "RedirectOutput",
        "UnixClient",
        "ShowReturnValue"
    ],
    "host": "localhost",
    "justMyCode": true,
    "showReturnValue": true,
    "workspaceFolder": "/home/esnow/projects/work/test_projects/gh-8384"
}
11 Client --> Adapter:
{
    "command": "initialize",
    "arguments": {
        "clientID": "vscode",
        "clientName": "Visual Studio Code - Insiders",
        "adapterID": "python",
        "pathFormat": "path",
        "linesStartAt1": true,
        "columnsStartAt1": true,
        "supportsVariableType": true,
        "supportsVariablePaging": true,
        "supportsRunInTerminalRequest": true,
        "locale": "en-us"
    },
    "type": "request",
    "seq": 1
}
29 Exit:
Exit-Code: 2
Signal: none
29 Error:
{}
30 Client --> Adapter:
{
    "command": "disconnect",
    "arguments": {
        "restart": false
    },
    "type": "request",
    "seq": 2
}
30 Error:
{}
1037 Stopping Session

@int19h
Copy link

int19h commented Dec 3, 2019

... and it looks like we need to do a better job at reporting that error in a way that's visible to the user. If you run this with "logToFile": true, you should see the error in ptvsd.adapter.*.log, but it's not propagated in the response to the "attach" DAP request, so VSC doesn't display it.

@ericsnowcurrently
Copy link
Member

I tried running that command, but it didn't help.

debugger.vscode_b2a7c9e5-7a55-42be-8ce6-ee621e1838d5.log:

0 Starting Session:
{
    "name": "Attach to Process",
    "type": "python",
    "request": "attach",
    "processId": 30606,
    "pathMappings": [
        {
            "localRoot": "/home/esnow/projects/work/test_projects/gh-8384",
            "remoteRoot": "."
        }
    ],
    "logToFile": true,
    "debugOptions": [
        "RedirectOutput",
        "UnixClient",
        "ShowReturnValue"
    ],
    "host": "localhost",
    "justMyCode": true,
    "showReturnValue": true,
    "workspaceFolder": "/home/esnow/projects/work/test_projects/gh-8384"
}
10 Client --> Adapter:
{
    "command": "initialize",
    "arguments": {
        "clientID": "vscode",
        "clientName": "Visual Studio Code - Insiders",
        "adapterID": "python",
        "pathFormat": "path",
        "linesStartAt1": true,
        "columnsStartAt1": true,
        "supportsVariableType": true,
        "supportsVariablePaging": true,
        "supportsRunInTerminalRequest": true,
        "locale": "en-us"
    },
    "type": "request",
    "seq": 1
}
26 Exit:
Exit-Code: 2
Signal: none
27 Error:
{}
28 Client --> Adapter:
{
    "command": "disconnect",
    "arguments": {
        "restart": false
    },
    "type": "request",
    "seq": 2
}
28 Error:
{}
1035 Stopping Session

@ericsnowcurrently
Copy link
Member

Also, I already have "logToFile": true in my config.

@ericsnowcurrently
Copy link
Member

I don't see any log file with "ptvsd" in the name.

@int19h
Copy link

int19h commented Dec 3, 2019

Looking closely at the debug config, it has "host":"localhost" - is that intentional? Technically, "host"/"port" and "processId" are mutually exclusive - you either attach to a socket, or you attach to a PID. This is validated on ptvsd side, but I don't think it even gets to the point where ptvsd is spawned - most likely, the extension-side logic checks for "host" first, and if present, assumes that it's attach-by-socket, and tries to connect you directly to the (nonexisting) ptvsd it expects to be running. Try removing "host" and see if that helps.

@ericsnowcurrently
Copy link
Member

It turns out everything is fine. :) I failed to notice that the commands @karthiknadig provided used backslashes. After changing them to forward slashes everything worked.

@ghost ghost removed the needs PR label Dec 3, 2019
@ericsnowcurrently ericsnowcurrently removed their assignment Dec 3, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Dec 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-debugging feature-request Request for new features or functionality
Projects
None yet
Development

No branches or pull requests

5 participants