Add lldb attach-to-PID option for debugpy on Linux - #2052
Conversation
Add an option to prefer lldb (falling back to gdb) when attaching to a process by PID on Linux. debugpy's attach-by-PID flow injects the debug server into a target process. On Linux it has always shelled out to gdb; on macOS it uses lldb. In some environments lldb is the available/preferred injector on Linux. This adds an opt-in preference, surfaced as a VS Code launch configuration option "linuxAttachPreferLldb". The selector flows end to end: adapter/clients.py reads linuxAttachPreferLldb from the attach request and forwards --linux-attach-prefer-lldb to the injector subprocess; server/cli.py parses that switch and sets the PYDEVD_ATTACH_PREFER_LLDB environment variable; add_code_to_python_process.py reads it at call time in the new run_python_code_linux dispatcher, which uses lldb when it is preferred and present on PATH, and otherwise transparently falls back to gdb. Implementation notes: - run_python_code_linux_lldb mirrors the existing run_python_code_mac lldb invocation but resolves the Linux .so via get_target_filename() and reuses the shared linux_and_mac/lldb_prepare.py driver. No native code changes are needed: both paths call the same exported DoAttach entry point. - The PEP 768 sys.remote_exec fast path (Python 3.14+) runs first and is unaffected; the lldb preference only applies on the gdb/lldb fallback path.
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
🔒 Automated review in progress — Rich Chiodo (@rchiodo) is auto-reviewing this PR. |
|
GitHub cannot anchor PR review comments to unchanged lines in the diff. Falling back to a general PR comment for tests/debugpy/server/test_cli.py:L390.
This assertion hard-codes |
| env.pop("PYTHONIOENCODING", None) | ||
| env.pop("PYTHONPATH", None) | ||
| print("Running: %s" % (" ".join(cmd))) | ||
| subprocess.check_call(" ".join(cmd), shell=True, env=env) |
There was a problem hiding this comment.
Warning · Non-blocking recommendation
run_python_code_linux_lldb duplicates the macOS lldb injector, including command construction, quoting, environment scrubbing, and subprocess execution. This creates two sources of truth for lldb fixes. Please extract the shared lldb flow into a helper, or explicitly document why the implementations must remain mirrored.
Rich Chiodo (rchiodo)
left a comment
There was a problem hiding this comment.
Approved via Review Center.
Extract the shared lldb injector, and fix a test that could fail spuriously depending on the ambient environment. run_python_code_linux_lldb duplicated run_python_code_mac in full: command construction, quoting, environment scrubbing, and subprocess execution were byte-identical apart from the .so/.dylib error message. Both are now thin wrappers over a shared _run_python_code_lldb(), which takes the library-not-found message as its only platform-specific input. Command generation and error text were verified unchanged against the previous implementation for both platforms. test_attach_to_pid_propagates_lldb_preference asserted show_debug_info=0, but attach_to_pid() derives that from DEBUGPY_ATTACH_BY_PID_DEBUG_INFO, which the test did not isolate. The variable is now cleared alongside PYDEVD_ATTACH_PREFER_LLDB, so the assertion stays exact and additionally pins the default. Tests are restructured to match: the shared flow is covered once against _run_python_code_lldb, and the platform wrappers are covered only for what they contribute - the error message and argument forwarding. They pass show_debug_info=7 rather than 0 so the assertions can distinguish a forwarded value from the default (is_debug is also 0 in the same command).
Rich Chiodo (rchiodo)
left a comment
There was a problem hiding this comment.
Approved via Review Center.
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
|
LGTM, thanks for the PR. I'll submit it once the tests pass. |
This MR contains the following updates: | Package | Type | Update | Change | OpenSSF | |---|---|---|---|---| | [debugpy](https://aka.ms/debugpy) ([source](https://github.com/microsoft/debugpy)) | dev | patch | `1.8.21` → `1.8.22` | [](https://securityscorecards.dev/viewer/?uri=github.com/microsoft/debugpy) | --- ### Release Notes <details> <summary>microsoft/debugpy (debugpy)</summary> ### [`v1.8.22`](https://github.com/microsoft/debugpy/releases/tag/v1.8.22): debugpy v1.8.22 [Compare Source](microsoft/debugpy@v1.8.21...v1.8.22) ##### Fixes - Fix invalid type annotation in test\_pydev\_monkey comprehension by [@​pdepetro](https://github.com/pdepetro) in [#​2033](microsoft/debugpy#2033) - Fix PEP 768 code injection SyntaxError when temp path contains backslashes by [@​rchiodo](https://github.com/rchiodo) with [@​Copilot](https://github.com/Copilot) in [#​2038](microsoft/debugpy#2038) - Fix race between adapter connection publication and session attachment by [@​aperez](https://github.com/aperez) in [#​2049](microsoft/debugpy#2049) - Fix debugger hang when expanding objects with blocking property getters ([#​2053](microsoft/debugpy#2053)) by [@​rchiodo](https://github.com/rchiodo) in [#​2055](microsoft/debugpy#2055) - Fix duplicate stopped event when two threads hit a breakpoint at once by [@​aperez](https://github.com/aperez) in [#​2056](microsoft/debugpy#2056) - Avoid exceptions in environment diagnostics by [@​rchiodo](https://github.com/rchiodo) in [#​2059](microsoft/debugpy#2059) - Fix thread identity when the first traced call is another thread's is\_alive() by [@​aperez](https://github.com/aperez) in [#​2061](microsoft/debugpy#2061) - Respect isolated mode when patching sys.path by [@​karandhaodiyal28-hash](https://github.com/karandhaodiyal28-hash) in [#​2050](microsoft/debugpy#2050) ##### Enhancements - Add trigger\_exception\_handler() for post-mortem debugging of caught exceptions by [@​nshepperd](https://github.com/nshepperd) in [#​1996](microsoft/debugpy#1996) - Add lldb attach-to-PID option for debugpy on Linux by [@​pdepetro](https://github.com/pdepetro) in [#​2052](microsoft/debugpy#2052) - Populate hitBreakpointIds in the DAP stopped event by [@​aperez](https://github.com/aperez) in [#​2060](microsoft/debugpy#2060) - Return the endpoint from listen() with the in-process adapter by [@​karandhaodiyal28-hash](https://github.com/karandhaodiyal28-hash) in [#​2051](microsoft/debugpy#2051) ##### Infrastructure work - Add Dependabot configuration for pip and GitHub Actions by [@​rchiodo](https://github.com/rchiodo) in [#​2041](microsoft/debugpy#2041) - Update vendored pydevd 3.4.1 -> 3.5.0 (maintenance refresh) by [@​rchiodo](https://github.com/rchiodo) in [#​2044](microsoft/debugpy#2044) - Pin secure test dependency floors and drop EOL Python 3.9/3.8 by [@​rchiodo](https://github.com/rchiodo) in [#​2045](microsoft/debugpy#2045) - Add more typing to debugpy and switch to 'standard' type checking mode by [@​rchiodo](https://github.com/rchiodo) in [#​1637](microsoft/debugpy#1637) - Add debugpy release agent by [@​rchiodo](https://github.com/rchiodo) in [#​2062](microsoft/debugpy#2062) - Pin GitHub Actions to full-length commit SHAs by [@​danfiedler-msft](https://github.com/danfiedler-msft) in [#​2063](microsoft/debugpy#2063) - Add python 3.15 to tests by [@​finnagin](https://github.com/finnagin) in [#​2069](microsoft/debugpy#2069) Thanks to [@​pdepetro](https://github.com/pdepetro), [@​rchiodo](https://github.com/rchiodo), [@​nshepperd](https://github.com/nshepperd), [@​aperez](https://github.com/aperez), [@​karandhaodiyal28-hash](https://github.com/karandhaodiyal28-hash), [@​danfiedler-msft](https://github.com/danfiedler-msft), and [@​finnagin](https://github.com/finnagin) for the commits. **Full Changelog**: <microsoft/debugpy@v1.8.21...v1.8.22> </details> --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xMDMuNSIsInVwZGF0ZWRJblZlciI6IjQ0LjEwMy41IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiLCJyZW5vdmF0ZSJdfQ==--> See merge request swiss-armed-forces/cyber-command/cea/loom!814
Add an option to prefer lldb (falling back to gdb) when attaching to a process by PID on Linux.
debugpy's attach-by-PID flow injects the debug server into a target process. On Linux it has always shelled out to gdb; on macOS it uses lldb. In some environments lldb is the available/preferred injector on Linux. This adds an opt-in preference, surfaced as a VS Code launch configuration option "linuxAttachPreferLldb".
The selector flows end to end: adapter/clients.py reads linuxAttachPreferLldb from the attach request and forwards --linux-attach-prefer-lldb to the injector subprocess; server/cli.py parses that switch and sets the PYDEVD_ATTACH_PREFER_LLDB environment variable; add_code_to_python_process.py reads it at call time in the new run_python_code_linux dispatcher, which uses lldb when it is preferred and present on PATH, and otherwise transparently falls back to gdb.
Implementation notes: