-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Expand file tree
/
Copy pathattachWaitFor.ts
More file actions
134 lines (110 loc) · 4.87 KB
/
attachWaitFor.ts
File metadata and controls
134 lines (110 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import * as os from 'os';
import * as vscode from 'vscode';
import { localize } from 'vscode-nls';
import * as util from '../common';
import { sleep } from '../Utility/Async/sleep';
import { CimAttachItemsProvider, PsAttachItemsProvider, WmicAttachItemsProvider } from './nativeAttach';
export interface WaitForProcessProvider {
poll(program: string, timeout: number, interval: number, token?: vscode.CancellationToken): Promise<string | undefined>
}
export class PollProcessProviderFactory {
static Get(): WaitForProcessProvider {
if (os.platform() === 'win32') {
const pwsh: string | undefined = util.findPowerShell();
let itemsProvider = pwsh ? new CimAttachItemsProvider(pwsh) : new WmicAttachItemsProvider();
return new PollWindowsProvider(itemsProvider);
} else {
// Linux and MacOS
return new PollProcProvider(new PsAttachItemsProvider());
}
}
}
export class PollProcProvider implements WaitForProcessProvider {
constructor(itemsProvider: PsAttachItemsProvider) {
this.itemsProvider = itemsProvider;
}
private itemsProvider: PsAttachItemsProvider;
async poll(program: string, timeout: number, interval: number, token?: vscode.CancellationToken): Promise<string | undefined> {
return new Promise<string | undefined>(async (resolve, reject) => {
const startTime = Date.now(); // Get the current time in milliseconds
let process: string | undefined;
while (true) {
let elapsedTime = Date.now() - startTime;
if (elapsedTime >= timeout) {
reject(new Error(localize("waitfor.timeout", "Timeout reached. No process matched the pattern.")));
}
if (token?.isCancellationRequested) {
reject(new Error(localize("waitfor.cancelled", "Operation cancelled.")));
}
let procs = await this.itemsProvider.getAttachItems(token)
for (const proc of procs) {
if (proc.detail?.includes(program)) {
process = proc.id
break
}
}
if (process) {
await util.execChildProcess(`kill -STOP ${process}`, undefined, undefined);
break
}
sleep(interval)
}
resolve(process)
})
}
}
export class PollWindowsProvider implements WaitForProcessProvider {
constructor(itemsProvider: CimAttachItemsProvider | WmicAttachItemsProvider) {
this.itemsProvider = itemsProvider;
}
private itemsProvider: CimAttachItemsProvider | WmicAttachItemsProvider;
public async poll(program: string, timeout: number, interval: number, token?: vscode.CancellationToken): Promise<string | undefined> {
return new Promise<string | undefined>(async (resolve, reject) => {
const startTime = Date.now(); // Get the current time in milliseconds
let process: string | undefined;
while (true) {
const elapsedTime = Date.now() - startTime;
if (elapsedTime >= timeout) {
reject(new Error(localize("waitfor.timeout", "Timeout reached. No process matched the pattern.")));
}
// Check for cancellation
if (token?.isCancellationRequested) {
reject(new Error(localize("waitfor.cancelled", "Operation cancelled.")));
}
let procs = await this.itemsProvider.getAttachItems(token)
for (const proc of procs) {
if (proc.detail?.includes(program)) {
process = proc.id
break
}
}
if (process) {
// Use pssupend to send SIGSTOP analogous in Windows
await util.execChildProcess(`pssuspend.exe /accepteula -nobanner ${process}`, undefined, undefined)
break
}
sleep(interval)
}
resolve(process)
})
}
}
export class AttachWaitFor {
constructor(poller: WaitForProcessProvider) {
//this._channel = vscode.window.createOutputChannel('waitfor-attach');
this.poller = poller;
}
// Defaults: ms
private timeout: number = 10000;
private interval: number = 150;
private poller: WaitForProcessProvider;
public async WaitForProcess(program: string, timeout: number, interval: number, token?: vscode.CancellationToken): Promise<string | undefined> {
if (timeout) {
this.timeout = timeout;
}
if (interval) {
this.interval = interval;
}
return await this.poller.poll(program, this.timeout, this.interval, token);
}
}