-
-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathstale-version.ts
More file actions
58 lines (55 loc) · 2.16 KB
/
Copy pathstale-version.ts
File metadata and controls
58 lines (55 loc) · 2.16 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
import { unlinkSync } from "node:fs";
/**
* 0.8.10 — guard against the extension activating against a daemon that was
* launched by an older bundled version. The 0.8.5-launched Node process pins
* its ESM module graph at startup with hashed chunk filenames; later upgrades
* overwrite those files on disk, and dynamic imports for code-split chunks
* (e.g. perplexity_doctor's `doctor-XXXXX.mjs`) fail forever.
*
* Rule: any version difference is "stale". We do NOT compare semver — a lock
* from a future version is also wrong (the running daemon's chunk filenames
* won't match what's on disk after a downgrade either).
*
* Lock missing / corrupt / pid-dead is intentionally NOT this helper's
* concern — the existing ensureDaemon flow handles those cases.
*/
export function isLockStale(
lock: { version?: string | null } | null | undefined,
bundledVersion: string,
): boolean {
if (!lock) return false;
// Older daemons predating the version field — treat as mismatch.
if (typeof lock.version !== "string" || lock.version.length === 0) return true;
return lock.version !== bundledVersion;
}
/** Best-effort unlink. Swallows ENOENT; rethrows nothing. */
export function removeStaleLock(lockPath: string): void {
try {
unlinkSync(lockPath);
} catch {
// already gone or unwritable; the spawn path will surface a clearer error
}
}
/**
* Send SIGTERM to the stale daemon's pid. Wrapped to swallow ESRCH (already
* dead) and downgrade EPERM (different owner / pid recycled into a system
* process) to a logged warning so activation never throws here. Any failure
* to bind the new daemon's port is a separate problem the existing
* ensure-loop already surfaces.
*/
export function killStaleDaemonPid(
pid: number,
log: (line: string) => void,
): void {
try {
process.kill(pid, "SIGTERM");
} catch (err) {
const code = (err as { code?: string } | null)?.code;
if (code === "ESRCH") return; // already gone
if (code === "EPERM") {
log(`[daemon] kill(${pid}) returned EPERM — pid not owned by us, continuing`);
return;
}
log(`[daemon] kill(${pid}) failed: ${err instanceof Error ? err.message : String(err)}`);
}
}