Skip to content

Commit 8fd5e03

Browse files
author
Borja Munoz Fernandez
committed
let's og
1 parent b49c1d1 commit 8fd5e03

File tree

8 files changed

+10998
-814
lines changed

8 files changed

+10998
-814
lines changed

Extension/.npmrc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +0,0 @@
1-
registry=https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/
2-
always-auth=true

Extension/package-lock.json

Lines changed: 10112 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Extension/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4692,6 +4692,11 @@
46924692
"type": "number",
46934693
"description": "%c_cpp.debuggers.waitFor.timeout.description%",
46944694
"default": 30000
4695+
},
4696+
"interval": {
4697+
"type": "number",
4698+
"description": "%c_cpp.debuggers.waitFor.interval.description%",
4699+
"default": 150
46954700
}
46964701
}
46974702
},
@@ -6611,6 +6616,7 @@
66116616
"@types/shell-quote": "^1.7.5",
66126617
"@types/sinon": "^17.0.3",
66136618
"@types/tmp": "^0.2.6",
6619+
"@types/vscode": "^1.99.1",
66146620
"@types/which": "^2.0.2",
66156621
"@types/yauzl": "^2.10.3",
66166622
"@typescript-eslint/eslint-plugin": "^6.1.0",

Extension/package.nls.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,10 @@
974974
"c_cpp.debuggers.VSSymbolOptionsModuleFilter.excludedModules.description": "Array of modules that the debugger should NOT load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadAllButExcluded'.",
975975
"c_cpp.debuggers.VSSymbolOptionsModuleFilter.includedModules.description": "Array of modules that the debugger should load symbols for. Wildcards (example: MyCompany.*.dll) are supported.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.",
976976
"c_cpp.debuggers.VSSymbolOptionsModuleFilter.includeSymbolsNextToModules.description": "If true, for any module NOT in the 'includedModules' array, the debugger will still check next to the module itself and the launching executable, but it will not check paths on the symbol search list. This option defaults to 'true'.\n\nThis property is ignored unless 'mode' is set to 'loadOnlyIncluded'.",
977+
"c_cpp.debuggers.waitFor.enabled.description": "If true, the debugger will wait till timeout to match a process cmd pattern and attach to it. If matched, sends a SIGSTOP to the process before attaching.",
978+
"c_cpp.debuggers.waitFor.pattern.description": "The process cmd pattern to match against. The pattern is a regular expression that will be matched against the process name.",
979+
"c_cpp.debuggers.waitFor.timeout.description": "The time, in milliseconds, to wait for a process to match. The default is 10000ms.",
980+
"c_cpp.debuggers.waitFor.interval.description": "The interval, in milliseconds, to wait between checks for the process to match. The default is 200ms.",
977981
"c_cpp.semanticTokenTypes.referenceType.description": "Style for C++/CLI reference types.",
978982
"c_cpp.semanticTokenTypes.cliProperty.description": "Style for C++/CLI properties.",
979983
"c_cpp.semanticTokenTypes.genericType.description": "Style for C++/CLI generic types.",
Lines changed: 100 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,125 @@
11

2+
import * as os from 'os';
23
import * as vscode from 'vscode';
34
import * as util from '../common';
45
import { sleep } from '../Utility/Async/sleep';
5-
import { PsProcessParser } from './nativeAttach';
6+
import { CimAttachItemsProvider, PsAttachItemsProvider, WmicAttachItemsProvider } from './nativeAttach';
67

7-
export class AttachWaitFor {
8+
export interface WaitForProcessProvider {
9+
poll(program: string, timeout: number, interval: number, token?: vscode.CancellationToken): Promise<string | undefined>
10+
}
11+
12+
export class PollProcessProviderFactory {
13+
static Get(): WaitForProcessProvider {
14+
if (os.platform() === 'win32') {
15+
const pwsh: string | undefined = util.findPowerShell();
16+
let itemsProvider = pwsh ? new CimAttachItemsProvider(pwsh) : new WmicAttachItemsProvider();
17+
return new PollWindowsProvider(itemsProvider);
18+
} else {
19+
// Linux and MacOS
20+
return new PollProcProvider(new PsAttachItemsProvider());
21+
}
22+
}
23+
}
824

9-
constructor() {
25+
export class PollProcProvider implements WaitForProcessProvider {
26+
27+
constructor(itemsProvider: PsAttachItemsProvider) {
28+
this.itemsProvider = itemsProvider;
1029
this._channel = vscode.window.createOutputChannel('waitfor-attach');
11-
this.timeout = 30000
1230
}
1331

1432
private _channel: vscode.OutputChannel;
15-
private timeout: number;
33+
private itemsProvider: PsAttachItemsProvider;
1634

17-
public async WaitForProcess(program: string, timeout: number): Promise<string | undefined> {
18-
if (timeout) {
19-
this.timeout = timeout
20-
}
35+
async poll(program: string, timeout: number, interval: number, token?: vscode.CancellationToken): Promise<string | undefined> {
36+
return new Promise<string | undefined>(async (resolve, reject) => {
37+
const startTime = Date.now(); // Get the current time in milliseconds
38+
let process: string | undefined;
39+
while (true) {
40+
let elapsedTime = Date.now() - startTime;
41+
if (elapsedTime >= timeout) {
42+
reject(new Error('Timeout reached. No process matched the pattern.'));
43+
}
2144

22-
return await this.poll(program)
23-
}
45+
if (token?.isCancellationRequested) {
46+
reject(new Error('Operation cancelled.'));
47+
}
2448

25-
//Naive poll mechanism, parses /proc for a while till a match is found
26-
private async poll(program: string): Promise<string | undefined> {
27-
this._channel.clear()
28-
const startTime = Date.now(); // Get the current time in milliseconds
29-
let seen = new Set<string>();
30-
let process: string | undefined;
31-
while (true) {
32-
const elapsedTime = Date.now() - startTime;
33-
34-
if (elapsedTime >= this.timeout) {
35-
console.log('Timeout reached. No process matched pattern.');
36-
return undefined
49+
let procs = await this.itemsProvider.getAttachItems(token)
50+
for (const proc of procs) {
51+
if (proc.detail?.includes(program)) {
52+
process = proc.id
53+
break
54+
}
55+
}
56+
57+
if (process) {
58+
await util.execChildProcess(`kill -STOP ${process}`, undefined, this._channel);
59+
resolve(process)
60+
}
61+
62+
sleep(interval)
3763
}
64+
})
65+
}
66+
}
3867

39-
const output: string = await util.execChildProcess(PsProcessParser.psLinuxCommand, undefined, this._channel)
40-
const lines: string[] = output.split(/\r?\n/);
41-
const processes: string[] = lines.slice(1);
42-
const processAttach = PsProcessParser.ParseProcessFromPsArray(processes)
43-
.sort((a, b) => {
44-
if (a.name === undefined) {
45-
if (b.name === undefined) {
46-
return 0;
47-
}
48-
return 1;
49-
}
50-
if (b.name === undefined) {
51-
return -1;
52-
}
53-
const aLower: string = a.name.toLowerCase();
54-
const bLower: string = b.name.toLowerCase();
55-
if (aLower === bLower) {
56-
return 0;
68+
export class PollWindowsProvider implements WaitForProcessProvider {
69+
constructor(itemsProvider: CimAttachItemsProvider | WmicAttachItemsProvider) {
70+
this.itemsProvider = itemsProvider;
71+
}
72+
73+
private itemsProvider: CimAttachItemsProvider | WmicAttachItemsProvider;
74+
75+
public async poll(program: string, timeout: number, interval: number, token?: vscode.CancellationToken): Promise<string | undefined> {
76+
return new Promise<string | undefined>(async (resolve, reject) => {
77+
const startTime = Date.now(); // Get the current time in milliseconds
78+
let process: string | undefined;
79+
while (true) {
80+
const elapsedTime = Date.now() - startTime;
81+
if (elapsedTime >= timeout) {
82+
reject(new Error('Timeout reached. No process matched the pattern.'));
83+
}
84+
85+
// Check for cancellation
86+
if (token?.isCancellationRequested) {
87+
reject(new Error('Operation cancelled.'));
88+
}
89+
90+
let procs = await this.itemsProvider.getAttachItems(token)
91+
for (const proc of procs) {
92+
if (proc.detail?.includes(program)) {
93+
process = proc.id
94+
break
5795
}
58-
return aLower < bLower ? -1 : 1;
59-
})
60-
.map(p => p.toAttachItem());
61-
processAttach.forEach(p => {
62-
if (!process && p.detail!.includes(program)) {
63-
console.log("Found program waiting for with pid %s - info %s", p.id!, p.detail!)
64-
process = p.id!
65-
66-
// Send sigstop by default?
67-
util.execChildProcess(`kill -STOP ${process}`, undefined, this._channel)
68-
return
6996
}
7097

71-
if (seen.has(p.id!) == false && p.label != "ps" && !p.detail!.includes("ps")) {
72-
seen.add(p.id!)
98+
if (process) {
99+
// Use pssupend to send SIGSTOP analogous in Windows
100+
await util.execChildProcess(`pssuspend.exe /accepteula -nobanner ${process}`, undefined, undefined)
101+
resolve(process)
73102
}
74-
})
75103

76-
if (process) {
77-
return process
104+
sleep(interval)
78105
}
106+
})
107+
}
108+
}
79109

80-
sleep(200)
81-
}
110+
111+
export class AttachWaitFor {
112+
constructor(private poller: WaitForProcessProvider) {
113+
//this._channel = vscode.window.createOutputChannel('waitfor-attach');
114+
this.timeout = 30000
82115
}
83116

117+
private timeout: number;
118+
119+
public async WaitForProcess(program: string, timeout: number, interval: number, token?: vscode.CancellationToken): Promise<string | undefined> {
120+
if (timeout) {
121+
this.timeout = timeout
122+
}
123+
return await this.poller.poll(program, this.timeout, interval, token);
124+
}
84125
}

Extension/src/Debugger/extension.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,10 @@ export async function initialize(context: vscode.ExtensionContext): Promise<void
125125
}
126126
}
127127
}));
128+
129+
130+
131+
128132
}
129133

130134
export function dispose(): void {

Extension/tools/OptionsSchema.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,28 @@
595595
},
596596
"default": []
597597
},
598+
"WaitFor": {
599+
"type": "object",
600+
"description": "%c_cpp.debuggers.waitFor.description%",
601+
"default": {},
602+
"properties": {
603+
"timeout": {
604+
"type": "integer",
605+
"description": "%c_cpp.debuggers.waitFor.timeout.description%",
606+
"default": 10000
607+
},
608+
"interval": {
609+
"type": "integer",
610+
"description": "%c_cpp.debuggers.waitFor.interval.description%",
611+
"default": 150
612+
},
613+
"pattern": {
614+
"type": "string",
615+
"description": "%c_cpp.debuggers.waitFor.pattern.description%",
616+
"default": ""
617+
}
618+
}
619+
},
598620
"CppdbgLaunchOptions": {
599621
"type": "object",
600622
"required": [
@@ -936,6 +958,10 @@
936958
}
937959
]
938960
},
961+
"waitFor": {
962+
"$ref": "#/definitions/WaitFor",
963+
"description": "%c_cpp.debuggers.waitFor.description%"
964+
},
939965
"logging": {
940966
"$ref": "#/definitions/Logging",
941967
"description": "%c_cpp.debuggers.logging.description%"

0 commit comments

Comments
 (0)