Skip to content

New child process spawned with debugpy --connect not receiving breakpoints #1918

Open
@jborean93

Description

@jborean93

Environment data

  • debugpy version: 1.8.14
  • OS and version: Fedora 42
  • Python version (& distribution if applicable, e.g. Anaconda): CPython 3.11.13
  • Using VS Code or Visual Studio: VS Code

Actual behavior

Due to a complicated debugging environment I am trying to setup a launch configuration which spawns a Python process which in turn setups up an interactive terminal where new processes spawned in that terminal attaches to the VSCode client running the original launch request. For example I have this launch configuration

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python Debugger: Current File",
            "type": "debugpy",
            "request": "launch",
            "program": "debugpy_test.py",
            "console": "integratedTerminal",
            "logToFile": true
        },
    ]
}

debugpy_test.py is the following:

import os
import subprocess

from debugpy.server import cli as debugpy_cli

def main() -> None:
    host, addr = debugpy_cli.options.address
    access_token = debugpy_cli.options.adapter_access_token

    with open('child_test.py', 'w') as f:
        f.write("import os\nimport debugpy\n\nprint(f'PID={os.getpid()} - debugpy.is_client_connected={debugpy.is_client_connected()}')\na = 1\nb = ''")

    print(f"Launched PID {os.getpid()}\nSet breakpoint on line 5 and run\npython -m debugpy --connect {host}:{addr} --adapter-access-token {access_token} --log-to-stderr --wait-for-client child_test.py")
    subprocess.run(
        ['bash'],
        env=os.environ | {
            'DEBUGPY_RUNNING': 'false',
            'PYDEVD_DISABLE_FILE_VALIDATION': '1',
        })


if __name__ == '__main__':
    main()

When running it will print out a message like the following

Launched PID 103924
Set breakpoint on line 5 and run
python -m debugpy --connect 127.0.0.1:50865 --adapter-access-token ... --log-to-stderr --wait-for-client child_test.py

The child_test.py is created by debugpy_test.py with the following content

import os
import debugpy

print(f'PID={os.getpid()} - debugpy.is_client_connected={debugpy.is_client_connected()}')
a = 1
b = ''

In VSCode I set a breakpoint in child_test.py and run echo $$ to get the bash PID and then run the printed Python command to launch child_test.py through debugpy connecting back to the original socket of the launch request.

The logs from stderr show that it connects and sets the pydevd.settrace after connecting back to the socket.

I+00000.003: Also logging to "/home/jborean/.vscode-server/extensions/ms-python.debugpy-2025.8.0-linux-arm64/debugpy.server-104098.log".

I+00000.018: Initial environment:
             
             System paths:
                 sys.executable: /home/jborean/dev/ansible/.venv/bin/python(/home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu/bin/python3.11)
                 sys.prefix: /home/jborean/dev/ansible/.venv
                 sys.base_prefix: /home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu
                 sys.real_prefix: <missing>
                 site.getsitepackages(): /home/jborean/dev/ansible/.venv/lib/python3.11/site-packages
                 site.getusersitepackages(): /home/jborean/.local/lib/python3.11/site-packages
                 sys.path (site-packages): /home/jborean/dev/ansible/.venv/lib/python3.11/site-packages
                 sysconfig.get_path('stdlib'): /home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu/lib/python3.11
                 sysconfig.get_path('platstdlib'): /home/jborean/dev/ansible/.venv/lib/python3.11
                 sysconfig.get_path('purelib'): /home/jborean/dev/ansible/.venv/lib/python3.11/site-packages
                 sysconfig.get_path('platlib'): /home/jborean/dev/ansible/.venv/lib/python3.11/site-packages
                 sysconfig.get_path('include'): /home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu/include/python3.11
                 sysconfig.get_path('scripts'): /home/jborean/dev/ansible/.venv/bin
                 sysconfig.get_path('data'): /home/jborean/dev/ansible/.venv
                 os.__file__: /home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu/lib/python3.11/os.py
                 threading.__file__: /home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu/lib/python3.11/threading.py
                 debugpy.__file__: /home/jborean/dev/ansible/.venv/lib/python3.11/site-packages/debugpy/__init__.py
             
             Installed packages:
                 ...
                 debugpy==1.8.14

I+00000.018: sys.argv before parsing: ['/home/jborean/dev/ansible/.venv/lib/python3.11/site-packages/debugpy/__main__.py', '--connect', '127.0.0.1:50865', '--adapter-access-token', 'a9c8d7e399cf091be4b665cab7001020f631369833f9e84bcf1856bedcfc1c6b', '--log-to-stderr', '--wait-for-client', 'child_test.py']
                      after parsing:  ['/home/jborean/dev/ansible/.venv/lib/python3.11/site-packages/debugpy/__main__.py']

D+00000.018: sys.argv after patching: ['child_test.py']

D+00000.018: configure({'qt': 'none', 'subProcess': True}, {})

D+00000.018: connect(('127.0.0.1', 50865), **{'access_token': 'a9c8d7e399cf091be4b665cab7001020f631369833f9e84bcf1856bedcfc1c6b'})

I+00000.019: Initial debug configuration: {
                 "qt": "none",
                 "subProcess": true,
                 "python": "/home/jborean/dev/ansible/.venv/bin/python",
                 "pythonEnv": {}
             }

D+00000.019: pydevd.settrace(*(), **{'host': '127.0.0.1', 'port': 50865, 'client_access_token': 'a9c8d7e399cf091be4b665cab7001020f631369833f9e84bcf1856bedcfc1c6b', 'suspend': False, 'patch_multiprocessing': True, 'dont_trace_start_patterns': ('/home/jborean/dev/ansible/.venv/lib/python3.11/site-packages/debugpy',), 'dont_trace_end_patterns': ('debugpy_launcher.py',)})

D+00000.172: wait_for_client()

I+00000.208: Pre-launch environment:
             
             System paths:
                 sys.executable: /home/jborean/dev/ansible/.venv/bin/python(/home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu/bin/python3.11)
                 sys.prefix: /home/jborean/dev/ansible/.venv
                 sys.base_prefix: /home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu
                 sys.real_prefix: <missing>
                 site.getsitepackages(): /home/jborean/dev/ansible/.venv/lib/python3.11/site-packages
                 site.getusersitepackages(): /home/jborean/.local/lib/python3.11/site-packages
                 sys.path (site-packages): /home/jborean/dev/ansible/.venv/lib/python3.11/site-packages
                 sysconfig.get_path('stdlib'): /home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu/lib/python3.11
                 sysconfig.get_path('platstdlib'): /home/jborean/dev/ansible/.venv/lib/python3.11
                 sysconfig.get_path('purelib'): /home/jborean/dev/ansible/.venv/lib/python3.11/site-packages
                 sysconfig.get_path('platlib'): /home/jborean/dev/ansible/.venv/lib/python3.11/site-packages
                 sysconfig.get_path('include'): /home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu/include/python3.11
                 sysconfig.get_path('scripts'): /home/jborean/dev/ansible/.venv/bin
                 sysconfig.get_path('data'): /home/jborean/dev/ansible/.venv
                 os.__file__: /home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu/lib/python3.11/os.py
                 threading.__file__: /home/jborean/.local/share/uv/python/cpython-3.11.13-linux-aarch64-gnu/lib/python3.11/threading.py
                 debugpy.__file__: /home/jborean/dev/ansible/.venv/lib/python3.11/site-packages/debugpy/__init__.py
             
             Installed packages:
                 ...
                 debugpy==1.8.14

I+00000.208: Running file 'child_test.py'

PID=104098 - debugpy.is_client_connected=False

Unfortunately the VSCode client does not receive the breakpoint event and the script just completes.

When looking at the logs I see the following:

  • debugger.vscode_{guid}.log - contains the exchange between VSCode the launched debugpy_test.py from the launch configuration and nothing about child_test.py
  • debugpy.adapter.{x}.log
    • I see the VSCode client connection and breakpoint message exhanges
    • I also see things like child_test.py Accepted incoming Server connection from 127.0.0.1:xxxx
    • This new connection does the negotiation exchange but I see things like
    • No active debug session for parent process of Server[pid=x] and
    • No clients to wait for - unblocking Server[pid=x]
    • It then sends the configurationDone request with no breakpoint
    • This tells me the sub process connects back to the VSCode side but it isn't detecting it should be part of the VSCode client that did the original launch

I'm assuming what is happening is that the adapter is getting the parent PID of child_test.py and finding it is the bash process and not debugpy_test.py that is the originally launched Python script. Because of this it just ignores the connection and continues on as normal.

If that is the case is there any way I can get this working while still including that interactive prompt to allow people to run whatever scenario they need under the debug context?

Expected behavior

The child process to be debuggable like normal sub processes.

Steps to reproduce:

See Actual behaviour

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions