Add processFilter for remote attach process selection - #14684
Conversation
|
@microsoft-github-policy-service agree company="Siemens AG"
|
There was a problem hiding this comment.
Pull request overview
Adds regex-based remote process selection for cppdbg attach configurations.
Changes:
- Filters remote process candidates by label, description, or detail.
- Automatically attaches on one match and narrows the picker on multiple matches.
- Adds configuration schema, documentation, and unit tests.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
Extension/src/Debugger/processFilter.ts |
Implements process filtering and regex validation. |
Extension/src/Debugger/attachToProcess.ts |
Applies filtering during remote attach. |
Extension/test/unit/processFilter.test.ts |
Tests matching and validation behavior. |
Extension/package.json |
Defines the processFilter configuration property. |
Extension/package.nls.json |
Documents the new property. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The old ATTACH mode started gdbserver with "--attach :<port> $(pidof <binary>)" and used a plain "request": "launch" config. This is the classic cpptools attach setup, which is fragile and has several long-standing, unfixed bugs, e.g. microsoft/vscode-cpptools#4166. { "name": "Attach with GDB", "type": "cppdbg", "request": "launch", "program": "<program>", "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "postDebugTask": "kill_gdbserver_..." } cppdbg also supports attaching over the extended-remote protocol: { "name": "Attach with GDB", "type": "cppdbg", "request": "attach", "program": "<program>", "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "useExtendedRemote": true } Switch to this instead: merge ATTACH into the same persistent "gdbserver --multi" server already used for MULTI mode, since both are now extended-remote sessions that only differ on the client side, and stop it by PID instead of pgrep/killall. ONCE mode gets the same readiness synchronization MULTI already had, since gdbserver now always writes a PID file that the stop commands wait on. Allocate a separate debug server port for each mode. This prevents the persistent attach endpoint from colliding with a once session for the same binary. Until microsoft/vscode-cpptools#14684 is merged, this comes with one downside (which was the blocker for using extended-remote attach mode until now): the user is prompted to pick the process to attach to, instead of it being selected automatically. But this is a temporary limitation, and the new setup is more robust and fixes several long-standing issues with the old ATTACH mode. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
The old ATTACH mode started gdbserver with "--attach :<port> $(pidof <binary>)" and used a plain "request": "launch" config. This is the classic cpptools attach setup, which is fragile and has several long-standing, unfixed bugs, e.g. microsoft/vscode-cpptools#4166. { "name": "Attach with GDB", "type": "cppdbg", "request": "launch", "program": "<program>", "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "postDebugTask": "kill_gdbserver_..." } cppdbg also supports attaching over the extended-remote protocol: { "name": "Attach with GDB", "type": "cppdbg", "request": "attach", "program": "<program>", "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "useExtendedRemote": true } Switch to this instead: merge ATTACH into the same persistent "gdbserver --multi" server already used for MULTI mode, since both are now extended-remote sessions that only differ on the client side, and stop it by PID instead of pgrep/killall. ONCE mode gets the same readiness synchronization MULTI already had, since gdbserver now always writes a PID file that the stop commands wait on. Allocate a separate debug server port for each mode. This prevents the persistent attach endpoint from colliding with a once session for the same binary. Until microsoft/vscode-cpptools#14684 is merged, this comes with one downside (which was the blocker for using extended-remote attach mode until now): the user is prompted to pick the process to attach to, instead of it being selected automatically. But this is a temporary limitation, and the new setup is more robust and fixes several long-standing issues with the old ATTACH mode. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
The old ATTACH mode started gdbserver with "--attach :<port> $(pidof <binary>)" and used a plain "request": "launch" config. This is the classic cpptools attach setup, which is fragile and has several long-standing, unfixed bugs, e.g. microsoft/vscode-cpptools#4166. { "name": "Attach with GDB", "type": "cppdbg", "request": "launch", "program": "<program>", "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "postDebugTask": "kill_gdbserver_..." } cppdbg also supports attaching over the extended-remote protocol: { "name": "Attach with GDB", "type": "cppdbg", "request": "attach", "program": "<program>", "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "useExtendedRemote": true } Switch to this instead: merge ATTACH into the same persistent "gdbserver --multi" server already used for MULTI mode, since both are now extended-remote sessions that only differ on the client side, and stop it by PID instead of pgrep/killall. ONCE mode gets the same readiness synchronization MULTI already had, since gdbserver now always writes a PID file that the stop commands wait on. Allocate a separate debug server port for each mode. This prevents the persistent attach endpoint from colliding with a once session for the same binary. Until microsoft/vscode-cpptools#14684 is merged, this comes with one downside (which was the blocker for using extended-remote attach mode until now): the user is prompted to pick the process to attach to, instead of it being selected automatically. But this is a temporary limitation, and the new setup is more robust and fixes several long-standing issues with the old ATTACH mode. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
The old ATTACH mode started gdbserver with "--attach :<port> $(pidof <binary>)" and used a plain "request": "launch" config. This is the classic cpptools attach setup, which is fragile and has several long-standing, unfixed bugs, e.g. microsoft/vscode-cpptools#4166. { "name": "Attach with GDB", "type": "cppdbg", "request": "launch", "program": "<program>", "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "postDebugTask": "kill_gdbserver_..." } cppdbg also supports attaching over the extended-remote protocol: { "name": "Attach with GDB", "type": "cppdbg", "request": "attach", "program": "<program>", "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "useExtendedRemote": true } Switch to this instead: merge ATTACH into the same persistent "gdbserver --multi" server already used for MULTI mode, since both are now extended-remote sessions that only differ on the client side, and stop it by PID instead of pgrep/killall. ONCE mode gets the same readiness synchronization MULTI already had, since gdbserver now always writes a PID file that the stop commands wait on. Allocate a separate debug server port for each mode. This prevents the persistent attach endpoint from colliding with a once session for the same binary. Until microsoft/vscode-cpptools#14684 is merged, this comes with one downside (which was the blocker for using extended-remote attach mode until now): the user is prompted to pick the process to attach to, instead of it being selected automatically. But this is a temporary limitation, and the new setup is more robust and fixes several long-standing issues with the old ATTACH mode. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
The old ATTACH mode started gdbserver with "--attach :<port> $(pidof <binary>)" and used a plain "request": "launch" config. This is the classic cpptools attach setup, which is fragile and has several long-standing, unfixed bugs, e.g. microsoft/vscode-cpptools#4166. { "name": "Attach with GDB", "type": "cppdbg", "request": "launch", "program": "<program>", "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "postDebugTask": "kill_gdbserver_..." } cppdbg also supports attaching over the extended-remote protocol: { "name": "Attach with GDB", "type": "cppdbg", "request": "attach", "program": "<program>", "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "useExtendedRemote": true } Switch to this instead: merge ATTACH into the same persistent "gdbserver --multi" server already used for MULTI mode, since both are now extended-remote sessions that only differ on the client side, and stop it by PID instead of pgrep/killall. ONCE mode gets the same readiness synchronization MULTI already had, since gdbserver now always writes a PID file that the stop commands wait on. Allocate a separate debug server port for each mode. This prevents the persistent attach endpoint from colliding with a once session for the same binary. Until microsoft/vscode-cpptools#14684 is merged, this comes with one downside (which was the blocker for using extended-remote attach mode until now): the user is prompted to pick the process to attach to, instead of it being selected automatically. But this is a temporary limitation, and the new setup is more robust and fixes several long-standing issues with the old ATTACH mode. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
The old ATTACH mode started gdbserver with "--attach :<port> $(pidof <binary>)" and used a plain "request": "launch" config. This is the classic cpptools attach setup, which is fragile and has several long-standing, unfixed bugs, e.g. microsoft/vscode-cpptools#4166. { "name": "Attach with GDB", "type": "cppdbg", "request": "launch", "program": "<program>", "stopAtEntry": true, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "postDebugTask": "kill_gdbserver_..." } cppdbg also supports attaching over the extended-remote protocol: { "name": "Attach with GDB", "type": "cppdbg", "request": "attach", "program": "<program>", "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "<target>:<port>", "useExtendedRemote": true } Switch to this instead: merge ATTACH into the same persistent "gdbserver --multi" server already used for MULTI mode, since both are now extended-remote sessions that only differ on the client side, and stop it by PID instead of pgrep/killall. ONCE mode gets the same readiness synchronization MULTI already had, since gdbserver now always writes a PID file that the stop commands wait on. Allocate a separate debug server port for each mode. This prevents the persistent attach endpoint from colliding with a once session for the same binary. Until microsoft/vscode-cpptools#14684 is merged, this comes with one downside (which was the blocker for using extended-remote attach mode until now): the user is prompted to pick the process to attach to, instead of it being selected automatically. But this is a temporary limitation, and the new setup is more robust and fixes several long-standing issues with the old ATTACH mode. Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
When attaching to a process on a remote target, the process always has to be selected by hand, even though the launch configuration already knows which executable it belongs to. A generated configuration cannot hard-code processId either, because the pid changes on every boot and on every restart of the service, so the picker is the only option. Add an optional processFilter regular expression to the cppdbg attach configuration. When set, it is matched against the label, description and detail of the remote process list: exactly one match attach to that process directly more than one show the picker with only the matching entries no match show the full picker, as before All three fields are considered because the item format depends on the transport: useExtendedRemote reports the user and the full command line in the label, while pipeTransport reports the process name in the label and the command line in the detail. An invalid regular expression is reported instead of being silently ignored. This affects remote attach only (pipeTransport and useExtendedRemote); local attach continues to use program-based matching. Closes microsoft#14682
Move the matching logic out of RemoteAttachPicker into a standalone function so that it can be unit tested without a VS Code quick pick or a live connection to a remote target. No functional change.
Cover empty and non-string filter values, matching against label, description and detail, multiple matches, and an invalid regular expression.
16a545f to
171cb46
Compare
Sean McManus (sean-mcmanus)
left a comment
There was a problem hiding this comment.
✨Copilot (agent135): [Moderate] Two correctness findings and one localization finding are noted inline.
|
|
||
| export function filterProcessItems<T extends ProcessFilterItem>(items: T[], processFilter?: unknown): T[] | undefined { | ||
| // The value comes from launch.json, so it is not guaranteed to be a string. | ||
| const trimmedFilter: string | undefined = typeof processFilter === 'string' ? processFilter.trim() : undefined; |
There was a problem hiding this comment.
✨Copilot (agent135): [Moderate] Please preserve the configured regex here. Leading and trailing whitespace is valid regex syntax: for example, ^my-daemon intentionally does not match my-daemon-helper, but trimming changes it to ^my-daemon. If that broadened expression has exactly one match, the code silently auto-attaches to the wrong PID instead of falling back to the picker. Trimming can still be used to detect an empty/all-whitespace value, but construct RegExp from the original string and add an edge-whitespace test.
| ] | ||
| }, | ||
| "processFilter": { | ||
| "type": "string", |
There was a problem hiding this comment.
✨Copilot (agent135): [Moderate] Please add this property to Extension/tools/OptionsSchema.json under CppdbgAttachOptions and regenerate this file. OptionsSchema.json is the documented schema source, and generateOptionsSchema.ts replaces the complete cppdbg attach schema in package.json from it. As written, the next yarn generate-options-schema removes processFilter, including its completion, validation, and documentation. This same source/generated drift previously required #14523 to resynchronize.
| try { | ||
| processRegex = new RegExp(trimmedFilter); | ||
| } catch { | ||
| throw new Error(`Invalid processFilter regular expression: ${trimmedFilter}`); |
There was a problem hiding this comment.
✨Copilot (agent135): [Minor] This newly introduced exception is user-facing through both remote-picker invocation paths, but its text is hard-coded English. Please route it through the existing vscode-nls/package.nls.json localization path (locking the processFilter identifier as appropriate) so localized installations receive a translated diagnostic.
Problem
When attaching to a process on a remote target (
useExtendedRemoteorpipeTransport), the process to attach to always has to be picked manually from the full process list on every debug session, even though a generatedlaunch.jsonalready knows which executable it targets. The PID can't be hard-coded because it changes on every restart/boot, and picking the wrong entry silently produces a session with mismatched symbols and source mappings.This mirrors the existing
program-based auto-selection already used for local attach (findProcessByProgramName), which does not apply to remote attach because the remote process list comes from a different source (RemoteAttachPicker) and itslabel/detailshapes differ per transport.Solution
Adds an optional
processFilter(regular expression) to thecppdbgattach configuration:label,description, anddetailof each remote process entry (the exact fields differ by transport:useExtendedRemoteputs the user + full command line inlabel;pipeTransportputs the process name inlabeland the command line indetail).Scope: this only affects remote attach (
pipeTransport/useExtendedRemote). Local attach is unaffected by this PR.Example
launch.json:{ "name": "attach my-daemon", "type": "cppdbg", "request": "attach", "program": "/path/on/build/host/to/unstripped/my-daemon", "MIMode": "gdb", "miDebuggerPath": "/path/to/aarch64-poky-linux-gdb", "miDebuggerServerAddress": "192.168.7.2:1234", "useExtendedRemote": true, "processFilter": "/usr/bin/my-daemon" }Closes #14682.
Open question for maintainers
Should
processFilteralso apply to local attach, in addition to (or instead of) the existingprogram-based basename matching? Sinceprogramis a required field forcppdbgattach, both would typically be present locally at the same time, so the semantics need a decision — I'd lean towards intersecting with theprogrammatch (never lettingprocessFilteralone select a process unrelated toprogram) rather than giving it precedence, but wanted to keep this PR scoped to the originally requested remote-only case and get feedback before extending it.Testing
Extension/test/unit/processFilter.test.ts.gdbserver --multitarget withuseExtendedRemote: true:processFiltermatch attaches directly without showing the picker