bgrun 3.9.0 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* POST /api/stop/:name — Stop a running process
|
|
3
|
+
*
|
|
4
|
+
* Kills the registered PID, then kills anything remaining on the port.
|
|
5
|
+
* Sets PID to 0 to prevent reconciliation from hijacking unrelated processes.
|
|
3
6
|
*/
|
|
4
|
-
import { getProcess } from '../../../../../src/db';
|
|
5
|
-
import { isProcessRunning, terminateProcess } from '../../../../../src/platform';
|
|
7
|
+
import { getProcess, updateProcessPid } from '../../../../../src/db';
|
|
8
|
+
import { isProcessRunning, terminateProcess, getProcessPorts, killProcessOnPort } from '../../../../../src/platform';
|
|
6
9
|
import { measure } from 'measure-fn';
|
|
7
10
|
|
|
8
11
|
export async function POST(req: Request, { params }: { params: { name: string } }) {
|
|
@@ -15,9 +18,24 @@ export async function POST(req: Request, { params }: { params: { name: string }
|
|
|
15
18
|
|
|
16
19
|
const running = await isProcessRunning(proc.pid);
|
|
17
20
|
if (!running) {
|
|
18
|
-
|
|
21
|
+
// Already dead — mark PID as 0 to prevent reconciliation
|
|
22
|
+
updateProcessPid(name, 0);
|
|
23
|
+
return Response.json({ success: true, already_stopped: true });
|
|
19
24
|
}
|
|
20
25
|
|
|
26
|
+
// Detect ports BEFORE killing so we can clean them up
|
|
27
|
+
const ports = await getProcessPorts(proc.pid);
|
|
28
|
+
|
|
21
29
|
await measure(`Stop "${name}" (PID ${proc.pid})`, () => terminateProcess(proc.pid));
|
|
30
|
+
|
|
31
|
+
// Also kill anything still on the ports
|
|
32
|
+
for (const port of ports) {
|
|
33
|
+
await killProcessOnPort(port);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Mark PID as 0 — prevents reconcileProcessPids from re-attaching
|
|
37
|
+
// a random matching process as this one
|
|
38
|
+
updateProcessPid(name, 0);
|
|
39
|
+
|
|
22
40
|
return Response.json({ success: true });
|
|
23
41
|
}
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,8 @@ function getHomeDir() {
|
|
|
25
25
|
return os.homedir();
|
|
26
26
|
}
|
|
27
27
|
async function isProcessRunning(pid, command) {
|
|
28
|
+
if (pid <= 0)
|
|
29
|
+
return false;
|
|
28
30
|
return plat.measure(`PID ${pid} alive?`, async () => {
|
|
29
31
|
try {
|
|
30
32
|
if (command && (command.includes("docker run") || command.includes("docker-compose up") || command.includes("docker compose up"))) {
|
|
@@ -1041,6 +1043,7 @@ async function handleStop(name) {
|
|
|
1041
1043
|
for (const port of ports) {
|
|
1042
1044
|
await killProcessOnPort(port);
|
|
1043
1045
|
}
|
|
1046
|
+
updateProcessPid(name, 0);
|
|
1044
1047
|
announce(`Process '${name}' has been stopped (kept in registry).`, "Process Stopped");
|
|
1045
1048
|
}
|
|
1046
1049
|
async function handleDeleteAll() {
|
package/package.json
CHANGED
package/src/commands/cleanup.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { getProcess, removeProcessByName, removeProcess, getAllProcesses, removeAllProcesses } from "../db";
|
|
2
|
+
import { getProcess, removeProcessByName, removeProcess, getAllProcesses, removeAllProcesses, updateProcessPid } from "../db";
|
|
3
3
|
import { isProcessRunning, terminateProcess, getProcessPorts, killProcessOnPort, waitForPortFree } from "../platform";
|
|
4
4
|
import { announce, error } from "../logger";
|
|
5
5
|
import * as fs from "fs";
|
|
@@ -82,6 +82,10 @@ export async function handleStop(name: string) {
|
|
|
82
82
|
await killProcessOnPort(port);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
// Mark PID as 0 — prevents reconcileProcessPids from re-attaching
|
|
86
|
+
// a random matching process as this one
|
|
87
|
+
updateProcessPid(name, 0);
|
|
88
|
+
|
|
85
89
|
announce(`Process '${name}' has been stopped (kept in registry).`, "Process Stopped");
|
|
86
90
|
}
|
|
87
91
|
|
package/src/platform.ts
CHANGED
|
@@ -28,6 +28,9 @@ export function getHomeDir(): string {
|
|
|
28
28
|
* For Docker containers, checks container status instead of PID
|
|
29
29
|
*/
|
|
30
30
|
export async function isProcessRunning(pid: number, command?: string): Promise<boolean> {
|
|
31
|
+
// PID 0 means intentionally stopped — never alive
|
|
32
|
+
if (pid <= 0) return false;
|
|
33
|
+
|
|
31
34
|
return plat.measure(`PID ${pid} alive?`, async () => {
|
|
32
35
|
try {
|
|
33
36
|
// Docker container detection
|
|
@@ -318,7 +321,9 @@ export async function reconcileProcessPids(
|
|
|
318
321
|
): Promise<Map<string, number>> {
|
|
319
322
|
return await plat.measure('Reconcile PIDs', async () => {
|
|
320
323
|
const result = new Map<string, number>();
|
|
321
|
-
|
|
324
|
+
// Skip processes with PID=0 — these were intentionally stopped
|
|
325
|
+
// and should NOT be reconciled to avoid hijacking unrelated processes
|
|
326
|
+
const needsReconciliation = processes.filter(p => deadPids.has(p.pid) && p.pid > 0);
|
|
322
327
|
if (needsReconciliation.length === 0) return result;
|
|
323
328
|
|
|
324
329
|
try {
|