Repository: microsoft/ptvsd

Issue:
Unable to attach docker with version 5
## Environment data
- Python: 3.6.8
- ptvsd: 5.0.0a11
- VScode: 1.41.1
- OS: Darwin x64 18.7.0
- Docker OS: Ubuntu 18.04
- Python VScode extension: 2020.2.58250-dev

## Configuration
- VSCode **settings.json** contains:
```
"python.experiments.optInto": [
    "DebugAdapterFactory - experiment",
    "PtvsdWheels37 - experiment"
]
```
- **launch.json** configuration used.
```
{
    "name": "Python: Remote Attach",
    "type: "python",
    "request": "attach",
    "port": 5678,
    // "debugServer": 5678  // Tried with and without this line.
    "host": "localhost",
    "pathMappings": [
        {
            "localRoot": "${workspaceFolder}",
           "remoteRoot": "."
        }
    ]
}
```

- **script.py** to debug.
```
import ptvsd

ptvsd.enable_attach(address=('0.0.0.0', 5678))
ptvsd.wait_for_attach()  # Never goes beyond this point.

# Processes to debug
```

## Actual behaviour
I run the `script.py` from within my Docker image and it reaches the `wait_for_attach()`. Then, when trying to run the python remote attach from the VSCode debugger, nothing really happens. 
The loading blue bar appears for a second but then disappears.

## Expected behaviour
VSCode debugger attaches to the running script and it is debugged normally.

I know I am using a version that is in alpha. Everything seems to be correctly installed since if I run the debugger without attachment the `new_ptvsd` appears in the path of the console and works as expected.

I want to use this version because the project I am working on relies heavily on multiprocessing and, as far as I understand, ptvsd 4 does not support that (usually get errors related to process already started).

I also need to use the attach version of the debugger because I need to use the docker environment.

Not sure if I'm doing something wrong or the configuration I'm trying to use is not yet supported.

Thanks in advance!


Discussion:
@bernatpuig Can you get us the logs? use `"logToFile": true` in the launch.json. That will generate logs from VSCode side of the connection. the log should be in the python extension root directory.

On the container side, use `ptvsd.enable_attach(address=('0.0.0.0', 5678), log_dir="~/logs")` ensure that the logs directory exists. This should generate logs from the container side of the connection.

Please redact any personal information from the logs and share it.
Here they go:

## Container side

- **ptvsd.server-9254.log**
```
I+00000.008: Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic x86_64
             CPython 3.6.9 (64-bit)
             ptvsd 5.0.0a11

I+00000.014: ptvsd.server debug start environment:
             
             CPU count: 2
             
             System paths:
                 sys.prefix: /usr
                 sys.base_prefix: /usr
                 sys.real_prefix: <missing>
                 site.getsitepackages(): /usr/lib/python3.6/dist-packages
                                         /usr/lib/python3/dist-packages
                                         /usr/local/lib/python3.6/dist-packages
                 site.getusersitepackages(): /root/.local/lib/python3.6/site-packages
                 sysconfig.get_path('stdlib'): /usr/lib/python3.6
                 sysconfig.get_path('platstdlib'): /usr/lib/python3.6
                 sysconfig.get_path('purelib'): /usr/lib/python3.6/site-packages
                 sysconfig.get_path('platlib'): /usr/lib/python3.6/site-packages
                 sysconfig.get_path('include'): /usr/include/python3.6m
                 sysconfig.get_path('scripts'): /usr/bin
                 sysconfig.get_path('data'): /usr
                 os.__file__: /usr/lib/python3.6/os.py
                 threading.__file__: /usr/lib/python3.6/threading.py

D+00000.015: enable_attach(('0.0.0.0', 5678), '~/logs', True)

I+00000.016: Won't trace filenames starting with: [
                 "/usr/local/lib/python3.6/dist-packages/ptvsd"
             ]
             Won't trace filenames ending with: [
                 "ptvsd_launcher.py"
             ]

I+00000.017: Waiting for adapter endpoints on 127.0.0.1:42531...

I+00000.018: enable_attach() spawning adapter: [
                 "/usr/bin/python3",
                 "/usr/local/lib/python3.6/dist-packages/ptvsd/adapter",
                 "--for-server",
                 "42531",
                 "--host",
                 "0.0.0.0",
                 "--port",
                 "5678",
                 "--server-access-token",
                 "<access_token>",
                 "--log-dir",
                 "~/logs"
             ]

I+00000.168: Endpoints received from adapter: {
                 "server": {
                     "host": "127.0.0.1",
                     "port": 43291
                 },
                 "ide": {
                     "host": "127.0.0.1",
                     "port": 5678
                 }
             }

I+00000.169: Adapter is accepting incoming IDE connections on 0.0.0.0:5678

D+00000.170: pydevd.settrace(*(), **{'host': '127.0.0.1', 'port': 43291, 'suspend': False, 'patch_multiprocessing': True, 'wait_for_ready_to_run': False, 'block_until_connected': True, 'dont_trace_start_patterns': ('/usr/local/lib/python3.6/dist-packages/ptvsd',), 'dont_trace_end_patterns': ('ptvsd_launcher.py',), 'access_token': '<access_token>', 'client_access_token': None})

I+00000.296: pydevd is connected to adapter at 127.0.0.1:43291

D+00000.300: wait_for_attach()
```

- **ptvsd.adapter-9268.log**
```
I+00000.025: Linux-4.9.184-linuxkit-x86_64-with-Ubuntu-18.04-bionic x86_64
             CPython 3.6.9 (64-bit)
             ptvsd 5.0.0a11

I+00000.038: ptvsd.adapter startup environment:
             
             CPU count: 2
             
             System paths:
                 sys.prefix: /usr
                 sys.base_prefix: /usr
                 sys.real_prefix: <missing>
                 site.getsitepackages(): /usr/lib/python3.6/dist-packages
                                         /usr/lib/python3/dist-packages
                                         /usr/local/lib/python3.6/dist-packages
                 site.getusersitepackages(): /root/.local/lib/python3.6/site-packages
                 sysconfig.get_path('stdlib'): /usr/lib/python3.6
                 sysconfig.get_path('platstdlib'): /usr/lib/python3.6
                 sysconfig.get_path('purelib'): /usr/lib/python3.6/site-packages
                 sysconfig.get_path('platlib'): /usr/lib/python3.6/site-packages
                 sysconfig.get_path('include'): /usr/include/python3.6m
                 sysconfig.get_path('scripts'): /usr/bin
                 sysconfig.get_path('data'): /usr
                 os.__file__: /usr/lib/python3.6/os.py
                 threading.__file__: /usr/lib/python3.6/threading.py

I+00000.039: Listening for incoming Server connections on 127.0.0.1:43291...

I+00000.040: Listening for incoming IDE connections on 127.0.0.1:5678...

I+00000.041: Sending endpoints info to debug server at localhost:42531:
             {
                 "server": {
                     "host": "127.0.0.1",
                     "port": 43291
                 },
                 "ide": {
                     "host": "127.0.0.1",
                     "port": 5678
                 }
             }

I+00000.061: Accepted incoming Server connection from 127.0.0.1:37022.

D+00000.063: Starting message loop for channel Server[?]

D+00000.064: Server[?] <-- {
                 "seq": 1,
                 "type": "request",
                 "command": "pydevdAuthorize",
                 "arguments": {
                     "debugServerAccessToken": "<debugServerAccessToken>"
                 }
             }

D+00000.066: Server[?] --> {
                 "pydevd_cmd_id": 502,
                 "seq": 2,
                 "type": "response",
                 "request_seq": 1,
                 "success": true,
                 "command": "pydevdAuthorize",
                 "body": {
                     "clientAccessToken": null
                 }
             }

D+00000.068: Server[?] <-- {
                 "seq": 2,
                 "type": "request",
                 "command": "pydevdSystemInfo"
             }

D+00000.118: Server[?] --> {
                 "pydevd_cmd_id": 502,
                 "seq": 4,
                 "type": "response",
                 "request_seq": 2,
                 "success": true,
                 "command": "pydevdSystemInfo",
                 "body": {
                     "python": {
                         "version": "3.6.9final0",
                         "implementation": {
                             "name": "cpython",
                             "version": "3.6.9final0",
                             "description": "CPython"
                         }
                     },
                     "platform": {
                         "name": "linux"
                     },
                     "process": {
                         "pid": 9254,
                         "ppid": 9239,
                         "executable": "/usr/bin/python3",
                         "bitness": 64
                     },
                     "pydevd": {
                         "usingCython": false,
                         "usingFrameEval": false
                     }
                 }
             }

D+00000.120: Server[pid=9254] <-- {
                 "seq": 3,
                 "type": "request",
                 "command": "evaluate",
                 "arguments": {
                     "expression": "\nif 'ptvsd' not in sys.modules:\n    sys.path.insert(0, '/usr/local/lib/python3.6/dist-packages')\n    try:\n        import ptvsd\n    finally:\n        del sys.path[0]\n"
                 }
             }

D+00000.215: Server[pid=9254] --> {
                 "pydevd_cmd_id": 502,
                 "seq": 6,
                 "type": "response",
                 "request_seq": 3,
                 "success": true,
                 "command": "evaluate",
                 "body": {
                     "result": "",
                     "variablesReference": 0,
                     "presentationHint": {}
                 }
             }

I+00000.219: No active debug session for parent process of Server[pid=9254].

D+00019.575: Server[pid=9254] --> {
                 "pydevd_cmd_id": 129,
                 "seq": 8,
                 "type": "event",
                 "event": "terminated",
                 "body": {}
             }

D+00019.577: /handling #8 event "terminated" from Server[pid=9254]/
             Closing Server[pid=9254] message stream

D+00019.579: Exiting message loop for channel Server[pid=9254]: No more messages

I+00019.581: All debug servers disconnected; waiting for remaining sessions...
```

## VSCode side

- **debugger.vscode_xxx.log**

```
0 Starting Session:
{
    "name": "Python: Remote Attach",
    "type": "python",
    "request": "attach",
    "port": 5678,
    "host": "localhost",
    "logToFile": true,
    "pathMappings": [
        {
            "localRoot": "<localRoot>",
            "remoteRoot": "."
        }
    ],
    "debugOptions": [
        "RedirectOutput",
        "UnixClient",
        "ShowReturnValue"
    ],
    "justMyCode": true,
    "showReturnValue": true,
    "workspaceFolder": "<localRoot>"
}
17 Client --> Adapter:
{
    "command": "initialize",
    "arguments": {
        "clientID": "vscode",
        "clientName": "Visual Studio Code",
        "adapterID": "python",
        "pathFormat": "path",
        "linesStartAt1": true,
        "columnsStartAt1": true,
        "supportsVariableType": true,
        "supportsVariablePaging": true,
        "supportsRunInTerminalRequest": true,
        "locale": "en-gb"
    },
    "type": "request",
    "seq": 1
}
307 Client <-- Adapter:
{
    "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
            }
        ]
    }
}
308 Client --> Adapter:
{
    "command": "attach",
    "arguments": {
        "name": "Python: Remote Attach",
        "type": "python",
        "request": "attach",
        "port": 5678,
        "host": "localhost",
        "logToFile": true,
        "pathMappings": [
            {
                "localRoot": "<localRoot>",
                "remoteRoot": "."
            }
        ],
        "debugOptions": [
            "RedirectOutput",
            "UnixClient",
            "ShowReturnValue"
        ],
        "justMyCode": true,
        "showReturnValue": true,
        "workspaceFolder": "<localRoot>",
        "__sessionId": "2b0ccfcf-41f0-4bd0-8bd3-60c2825b6837"
    },
    "type": "request",
    "seq": 2
}
342 Client <-- Adapter:
{
    "seq": 0,
    "type": "event",
    "event": "terminated"
}
344 Client --> Adapter:
{
    "command": "disconnect",
    "arguments": {
        "restart": false
    },
    "type": "request",
    "seq": 3
}
462 Error:
{}
462 Exit:
Exit-Code: 0
Signal: none
1351 Stopping Session
```

@int19h Shouldn't the ide endpoint be `0.0.0.0`? it looks like we are setting ide endpoint to be 'localhost'?
```
I+00000.168: Endpoints received from adapter: {
                 "server": {
                     "host": "127.0.0.1",
                     "port": 43291
                 },
                 "ide": {
                     "host": "127.0.0.1",
                     "port": 5678
                 }
             }
```
Yep, it's a regression in the code that creates the IDE listening socket in the adapter. It's ignoring the host. 

Resolving patch:
diff --git a/src/ptvsd/adapter/__main__.py b/src/ptvsd/adapter/__main__.py
--- a/src/ptvsd/adapter/__main__.py
+++ b/src/ptvsd/adapter/__main__.py
@@ -58,7 +58,7 @@ def main(args):
     else:
         endpoints = {"server": {"host": server_host, "port": server_port}}
         try:
-            ide_host, ide_port = ide.listen(port=args.port)
+            ide_host, ide_port = ide.listen(host=args.host, port=args.port)
         except Exception as exc:
             if args.for_server is None:
                 raise
diff --git a/src/ptvsd/server/api.py b/src/ptvsd/server/api.py
--- a/src/ptvsd/server/api.py
+++ b/src/ptvsd/server/api.py
@@ -90,7 +90,7 @@ def enable_attach(dont_trace_start_patterns, dont_trace_end_patterns):
     server_access_token = compat.force_str(codecs.encode(os.urandom(32), "hex"))
 
     try:
-        endpoints_listener = sockets.create_server("127.0.0.1", 0, timeout=5)
+        endpoints_listener = sockets.create_server("127.0.0.1", 0, timeout=10)
     except Exception as exc:
         log.exception("Can't listen for adapter endpoints:")
         raise RuntimeError("can't listen for adapter endpoints: " + str(exc))


Test patch: