Skip to content

Commit bc7f2cc

Browse files
committed
fix: stop the process successful
1 parent 17211fe commit bc7f2cc

File tree

5 files changed

+68
-46
lines changed

5 files changed

+68
-46
lines changed

.changeset/eight-flowers-play.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"phpstan-vscode": patch
3+
---
4+
5+
Stop the process successful

src/commands/analyse.ts

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
parsePHPStanAnalyseResult,
44
PHPStanAnalyseResult,
55
} from "../utils/phpstan";
6-
import { waitForClose } from "../utils/process";
6+
import { killProcess, waitForClose } from "../utils/process";
77
import showOutput from "./showOutput";
88
import stopAnalyse from "./stopAnalyse";
99
import { spawn } from "child_process";
@@ -68,7 +68,7 @@ async function refreshDiagnostics(ext: Ext, result: PHPStanAnalyseResult) {
6868
async function rutine(ext: Ext, args?: string[]) {
6969
setStatusBarProgress(ext);
7070

71-
const childProcess = (ext.store.analyse.process = spawn(
71+
const childProcess = spawn(
7272
ext.settings.phpPath,
7373
[
7474
"-f",
@@ -87,29 +87,55 @@ async function rutine(ext: Ext, args?: string[]) {
8787
{
8888
cwd: ext.cwd,
8989
}
90-
));
91-
92-
childProcess.stdout.on("data", (buffer: Buffer) => ext.log(buffer));
93-
94-
childProcess.stderr.on("data", (buffer: Buffer) => {
95-
const progress = /(\d{1,3})%\s*$/.exec(buffer.toString())?.[1];
96-
if (progress) setStatusBarProgress(ext, Number(progress));
97-
ext.log(buffer);
90+
);
91+
92+
let stdout = "";
93+
let skipCloseError = false;
94+
const { channel } = ext.store.analyse;
95+
96+
channel.once("stop", async () => {
97+
skipCloseError = true;
98+
try {
99+
const killed = await killProcess(childProcess);
100+
ext.log({
101+
tag: "call",
102+
message: `killProcess (${killed ? "true" : "false"})`,
103+
});
104+
} catch (error) {
105+
ext.log(error as Error);
106+
}
98107
});
99108

100-
const [, stdout] = await waitForClose(childProcess);
101-
102-
ext.store.analyse.process = undefined;
103-
104-
const phpstanResult = parsePHPStanAnalyseResult(stdout);
109+
try {
110+
childProcess.stdout.on("data", (buffer: Buffer) => {
111+
stdout += buffer.toString();
112+
ext.log(buffer);
113+
});
114+
childProcess.stderr.on("data", (buffer: Buffer) => {
115+
const progress = /(\d{1,3})%\s*$/.exec(buffer.toString())?.[1];
116+
if (progress) setStatusBarProgress(ext, Number(progress));
117+
ext.log(buffer);
118+
});
119+
try {
120+
await waitForClose(childProcess);
121+
} catch (error) {
122+
if (skipCloseError) return;
123+
throw error;
124+
}
125+
} finally {
126+
channel.removeAllListeners();
127+
}
105128

106-
refreshDiagnostics(ext, phpstanResult);
129+
if (stdout) {
130+
const phpstanResult = parsePHPStanAnalyseResult(stdout);
131+
refreshDiagnostics(ext, phpstanResult);
132+
}
107133

108134
ext.clearStatusBar();
109135
}
110136

111137
export default async function analyse(ext: Ext, ms?: number, args?: string[]) {
112-
await stopAnalyse(ext);
138+
stopAnalyse(ext);
113139
ext.store.analyse.timeout.run(async () => {
114140
await rutine(ext, args);
115141
}, ms ?? ext.settings.analysedDelay);

src/commands/stopAnalyse.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import { Ext } from "../extension";
2-
import { killProcess } from "../utils/process";
32

4-
export default async function stopAnalyse(ext: Ext) {
5-
if (ext.store.analyse.process) {
6-
await killProcess(ext.store.analyse.process);
7-
ext.clearStatusBar();
8-
ext.store.analyse.process = undefined;
9-
}
3+
export default function stopAnalyse(ext: Ext) {
4+
ext.store.analyse.channel.emit("stop");
105
}

src/extension.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
getWorkspacePath,
1010
onChangeExtensionSettings,
1111
} from "./utils/vscode";
12-
import { ChildProcessWithoutNullStreams } from "child_process";
12+
import { EventEmitter } from "events";
1313
import {
1414
DiagnosticCollection,
1515
Disposable,
@@ -44,7 +44,7 @@ export type ExtStore = {
4444
timeout: DelayedTimeout;
4545
};
4646
analyse: {
47-
process?: ChildProcessWithoutNullStreams;
47+
channel: EventEmitter;
4848
timeout: DelayedTimeout;
4949
};
5050
fileWatcher: {
@@ -92,6 +92,7 @@ export class Ext<
9292
},
9393
analyse: {
9494
timeout: createDelayedTimeout(),
95+
channel: new EventEmitter(),
9596
},
9697
fileWatcher: {
9798
enabled: true,
@@ -227,7 +228,10 @@ export class Ext<
227228
tag: `event:${eventName}`,
228229
message: path,
229230
});
230-
return await this.options.commands.analyse(this);
231+
await this.call(
232+
async () => await this.options.commands.analyse(this),
233+
"analyse"
234+
);
231235
}
232236
}
233237
});

src/utils/process.ts

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,18 @@
1-
import { ChildProcessWithoutNullStreams, exec } from "child_process";
2-
import { platform } from "os";
1+
import { ChildProcess } from "child_process";
32

4-
export async function killProcess(
5-
process: ChildProcessWithoutNullStreams
6-
): Promise<void> {
7-
const os = platform();
8-
if (os === "win32") {
9-
return new Promise((resolve) => {
10-
exec(`taskkill /pid ${process.pid} /T /F`, () => resolve());
11-
});
12-
} else {
13-
process.kill();
3+
export async function killProcess(p: ChildProcess) {
4+
p.stdout?.removeAllListeners();
5+
p.stderr?.removeAllListeners();
6+
try {
7+
return p.kill("SIGKILL");
8+
} catch (error) {
9+
return false;
1410
}
1511
}
1612

17-
export async function waitForClose(
18-
childProcess: ChildProcessWithoutNullStreams
19-
) {
20-
return new Promise<[number | null, string]>((resolve, reject) => {
21-
let result = "";
22-
childProcess.stdout.on("data", (data) => (result += data));
13+
export async function waitForClose(childProcess: ChildProcess) {
14+
return new Promise<number | null>((resolve, reject) => {
2315
childProcess.on("error", reject);
24-
childProcess.on("close", (exitCode) => resolve([exitCode, result]));
16+
childProcess.on("close", (exitCode) => resolve(exitCode));
2517
});
2618
}

0 commit comments

Comments
 (0)