@gtkx/utils 2.0.0-beta.4 → 2.0.0-beta.6
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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-with-parent-death-signal.d.ts","sourceRoot":"","sources":["../../src/process/spawn-with-parent-death-signal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAiBjF,KAAK,uBAAuB,GAAG;IAC3B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC,CAAC;AAEF,KAAK,4BAA4B,GAAG,IAAI,CAAC,uBAAuB,EAAE,oBAAoB,CAAC,GAAG;IACtF,gBAAgB,EAAE,MAAM,CAAC;CAC5B,CAAC;
|
|
1
|
+
{"version":3,"file":"spawn-with-parent-death-signal.d.ts","sourceRoot":"","sources":["../../src/process/spawn-with-parent-death-signal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAS,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAiBjF,KAAK,uBAAuB,GAAG;IAC3B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC,CAAC;AAEF,KAAK,4BAA4B,GAAG,IAAI,CAAC,uBAAuB,EAAE,oBAAoB,CAAC,GAAG;IACtF,gBAAgB,EAAE,MAAM,CAAC;CAC5B,CAAC;AAgRF,QAAA,MAAM,kBAAkB,QAAO,IAY9B,CAAC;AAgFF,iBAAS,0BAA0B,CAC/B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE,uBAA4B,GACtC,YAAY,CAOd;AAED,QAAA,MAAM,8BAA8B,GAChC,SAAS,MAAM,EACf,MAAM,MAAM,EAAE,EACd,SAAS,4BAA4B,KACtC,YA2CF,CAAC;AAEF,OAAO,EAAE,0BAA0B,EAAE,8BAA8B,EAAE,kBAAkB,EAAE,CAAC"}
|
|
@@ -15,12 +15,14 @@ const guard = { jobs: new Map() };
|
|
|
15
15
|
const SUPERVISOR_NAME = "gtkx-process-supervisor";
|
|
16
16
|
const SUPERVISOR_CLEANUP_NAME = "gtkx-process-cleanup";
|
|
17
17
|
const SUPERVISOR_WATCH_NAME = "gtkx-process-watch";
|
|
18
|
-
const
|
|
18
|
+
const SUPERVISOR_KILL_GROUP_BODY = [
|
|
19
19
|
"remaining=40",
|
|
20
20
|
'while [ "$remaining" -gt 0 ] && kill -KILL "-$group" 2>/dev/null; do',
|
|
21
21
|
' "$sleep_command" 0.025',
|
|
22
22
|
" remaining=$((remaining - 1))",
|
|
23
23
|
"done",
|
|
24
|
+
];
|
|
25
|
+
const SUPERVISOR_REMOVE_RUNTIME_BODY = [
|
|
24
26
|
"remaining=40",
|
|
25
27
|
'while [ "$remaining" -gt 0 ] && ' +
|
|
26
28
|
'[ "$("$stat_command" -c "%d:%i:%u" -- "$runtime" 2>/dev/null)" = "$identity" ]; do',
|
|
@@ -29,6 +31,7 @@ const SUPERVISOR_CLEANUP_BODY = [
|
|
|
29
31
|
" remaining=$((remaining - 1))",
|
|
30
32
|
"done",
|
|
31
33
|
];
|
|
34
|
+
const SUPERVISOR_CLEANUP_BODY = [...SUPERVISOR_KILL_GROUP_BODY, ...SUPERVISOR_REMOVE_RUNTIME_BODY];
|
|
32
35
|
const SUPERVISOR_CLEANUP_SCRIPT = [
|
|
33
36
|
"runtime=$1",
|
|
34
37
|
"identity=$2",
|
|
@@ -58,14 +61,24 @@ const SUPERVISOR_WATCH_SCRIPT = [
|
|
|
58
61
|
' case "$1" in Z|X|x) return 1 ;; esac',
|
|
59
62
|
' [ "${20}" = "$expected_start" ]',
|
|
60
63
|
"}",
|
|
64
|
+
"matches_parent() {",
|
|
65
|
+
' matches_process "$expected_parent" "$expected_parent_start"',
|
|
66
|
+
"}",
|
|
67
|
+
"kill_group() {",
|
|
68
|
+
...SUPERVISOR_KILL_GROUP_BODY.map((line) => ` ${line}`),
|
|
69
|
+
"}",
|
|
61
70
|
"cleanup() {",
|
|
62
71
|
' trap "" TERM INT HUP',
|
|
63
|
-
|
|
72
|
+
" kill_group",
|
|
73
|
+
...SUPERVISOR_REMOVE_RUNTIME_BODY.map((line) => ` ${line}`),
|
|
64
74
|
" exit 0",
|
|
65
75
|
"}",
|
|
66
76
|
"trap cleanup TERM INT HUP",
|
|
67
|
-
'while matches_process "$group" "$group_start" && '
|
|
68
|
-
|
|
77
|
+
'while matches_process "$group" "$group_start" && matches_parent; do',
|
|
78
|
+
' "$sleep_command" 0.1',
|
|
79
|
+
"done",
|
|
80
|
+
"kill_group",
|
|
81
|
+
"while matches_parent; do",
|
|
69
82
|
' "$sleep_command" 0.1',
|
|
70
83
|
"done",
|
|
71
84
|
"cleanup",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spawn-with-parent-death-signal.js","sourceRoot":"","sources":["../../src/process/spawn-with-parent-death-signal.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcess, spawn, type StdioOptions } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\nimport { Socket } from \"node:net\";\nimport { dirname, extname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { killMarkedProcesses, PROCESS_MARKER } from \"./kill-marked-processes.ts\";\nimport {\n type CleanupDirectoryIdentity,\n cleanupDirectoryIdentity,\n killProcessGroup,\n type ProcessGroupIdentity,\n processGroupIdentity,\n removeCleanupDirectory,\n} from \"./kill-process-group.ts\";\nimport { resolveExecutable } from \"./resolve-executable.ts\";\n\ntype ParentDeathSpawnOptions = {\n stdio?: StdioOptions;\n env?: NodeJS.ProcessEnv;\n cleanupDirectories?: string[];\n};\n\ntype ParentDeathSupervisorOptions = Omit<ParentDeathSpawnOptions, \"cleanupDirectories\"> & {\n cleanupDirectory: string;\n};\n\ntype GuardSignal = \"SIGKILL\" | \"SIGCONT\";\n\ntype ProcessIdentity = {\n pid: number;\n startTime: string;\n};\n\ntype ProcessWatch = {\n owner: ProcessIdentity;\n target: ProcessIdentity;\n};\n\ntype LaunchArguments = (executable: string, cleanupDirectories: CleanupDirectoryIdentity[]) => string[];\n\ntype GuardJob = {\n marker: string;\n processGroup: ProcessGroupIdentity;\n cleanupDirectories: CleanupDirectoryIdentity[];\n signal: GuardSignal;\n};\n\ntype GuardState = {\n child?: ChildProcess | undefined;\n jobs: Map<string, GuardJob>;\n watch?: ProcessWatch;\n};\n\ntype SpawnRollback = {\n child: ChildProcess;\n marker: string;\n processGroup?: ProcessGroupIdentity;\n cleanupDirectories?: CleanupDirectoryIdentity[];\n};\n\nconst MODULE_PATH = fileURLToPath(import.meta.url);\nconst GUARD_PATH = join(dirname(MODULE_PATH), `process-guard${extname(MODULE_PATH)}`);\nconst RUN_ID = randomBytes(8).toString(\"hex\");\nconst RUN_PREFIX = `${PROCESS_MARKER}=${RUN_ID}/`;\nconst guard: GuardState = { jobs: new Map() };\nconst SUPERVISOR_NAME = \"gtkx-process-supervisor\";\nconst SUPERVISOR_CLEANUP_NAME = \"gtkx-process-cleanup\";\nconst SUPERVISOR_WATCH_NAME = \"gtkx-process-watch\";\nconst SUPERVISOR_CLEANUP_BODY = [\n \"remaining=40\",\n 'while [ \"$remaining\" -gt 0 ] && kill -KILL \"-$group\" 2>/dev/null; do',\n ' \"$sleep_command\" 0.025',\n \" remaining=$((remaining - 1))\",\n \"done\",\n \"remaining=40\",\n 'while [ \"$remaining\" -gt 0 ] && ' +\n '[ \"$(\"$stat_command\" -c \"%d:%i:%u\" -- \"$runtime\" 2>/dev/null)\" = \"$identity\" ]; do',\n ' \"$rm_command\" -rf -- \"$runtime\"',\n ' \"$sleep_command\" 0.025',\n \" remaining=$((remaining - 1))\",\n \"done\",\n];\nconst SUPERVISOR_CLEANUP_SCRIPT = [\n \"runtime=$1\",\n \"identity=$2\",\n \"group=$3\",\n \"stat_command=$4\",\n \"rm_command=$5\",\n \"sleep_command=$6\",\n ...SUPERVISOR_CLEANUP_BODY,\n].join(\"\\n\");\nconst SUPERVISOR_WATCH_SCRIPT = [\n \"runtime=$1\",\n \"identity=$2\",\n \"group=$3\",\n \"group_start=$4\",\n \"expected_parent=$5\",\n \"expected_parent_start=$6\",\n \"stat_command=$7\",\n \"rm_command=$8\",\n \"sleep_command=$9\",\n \"matches_process() {\",\n \" expected_process=$1\",\n \" expected_start=$2\",\n \" process_stat=\",\n ' IFS= read -r process_stat < \"/proc/$expected_process/stat\" || return 1',\n \" process_tail=${process_stat##*) }\",\n \" set -- $process_tail\",\n ' case \"$1\" in Z|X|x) return 1 ;; esac',\n ' [ \"${20}\" = \"$expected_start\" ]',\n \"}\",\n \"cleanup() {\",\n ' trap \"\" TERM INT HUP',\n ...SUPERVISOR_CLEANUP_BODY.map((line) => ` ${line}`),\n \" exit 0\",\n \"}\",\n \"trap cleanup TERM INT HUP\",\n 'while matches_process \"$group\" \"$group_start\" && ' +\n 'matches_process \"$expected_parent\" \"$expected_parent_start\"; do',\n ' \"$sleep_command\" 0.1',\n \"done\",\n \"cleanup\",\n].join(\"\\n\");\nconst SUPERVISOR_SCRIPT = [\n \"runtime=$1\",\n \"identity=$2\",\n \"expected_parent=$3\",\n \"expected_parent_start=$4\",\n \"stat_command=$5\",\n \"rm_command=$6\",\n \"shell_command=$7\",\n \"setsid_command=$8\",\n \"sleep_command=$9\",\n \"shift 9\",\n \"watch_name=$1\",\n \"watch_script=$2\",\n \"cleanup_name=$3\",\n \"cleanup_script=$4\",\n \"shift 4\",\n \"process_start() {\",\n \" process_stat=\",\n ' IFS= read -r process_stat < \"/proc/$1/stat\" || return 1',\n \" process_tail=${process_stat##*) }\",\n \" set -- $process_tail\",\n ' case \"$1\" in Z|X|x) return 1 ;; esac',\n ' printf \"%s\" \"${20}\"',\n \"}\",\n \"matches_parent() {\",\n \" parent_stat=\",\n ' IFS= read -r parent_stat < \"/proc/$expected_parent/stat\" || return 1',\n \" parent_tail=${parent_stat##*) }\",\n \" set -- $parent_tail\",\n ' case \"$1\" in Z|X|x) return 1 ;; esac',\n ' [ \"${20}\" = \"$expected_parent_start\" ]',\n \"}\",\n \"terminate() {\",\n ' trap \"\" CONT TERM INT HUP',\n \" while :; do\",\n ' \"$setsid_command\" \"$shell_command\" -c \"$cleanup_script\" \"$cleanup_name\" \"$runtime\" \"$identity\" \"$$\" ' +\n '\"$stat_command\" \"$rm_command\" \"$sleep_command\" </dev/null >/dev/null 2>&1 &',\n \" cleanup=$!\",\n ' wait \"$cleanup\" 2>/dev/null',\n ' \"$sleep_command\" 0.025',\n \" done\",\n \"}\",\n \"continue_or_terminate() {\",\n \" remaining=40\",\n ' while matches_parent && [ \"$remaining\" -gt 0 ]; do',\n ' \"$sleep_command\" 0.025',\n \" remaining=$((remaining - 1))\",\n \" done\",\n \" if ! matches_parent; then terminate; fi\",\n \"}\",\n \"trap continue_or_terminate CONT\",\n \"trap terminate TERM INT HUP\",\n \"supervisor_start=$(process_start \\\"$$\\\") || terminate\",\n '( unset GTKX_PROCESS_GUARD; exec \"$setsid_command\" \"$shell_command\" -c \"$watch_script\" \"$watch_name\" \"$runtime\" ' +\n '\"$identity\" \"$$\" \"$supervisor_start\" \"$expected_parent\" \"$expected_parent_start\" \"$stat_command\" ' +\n '\"$rm_command\" \"$sleep_command\" ) </dev/null >/dev/null 2>&1 &',\n \"child=\",\n \"if ! matches_parent; then terminate; fi\",\n '\"$@\" &',\n \"child=$!\",\n \"while :; do\",\n ' wait \"$child\"',\n \" status=$?\",\n ' if kill -0 \"$child\" 2>/dev/null; then continue; fi',\n ' exit \"$status\"',\n \"done\",\n].join(\"\\n\");\n\nconst processIdentity = (pid: number): ProcessIdentity => {\n const stat = readFileSync(`/proc/${String(pid)}/stat`, \"utf8\");\n const fields = stat.slice(stat.lastIndexOf(\") \") + 2).split(\" \", 20);\n const state = fields[0];\n const startTime = fields[19];\n\n if (startTime === undefined || state === undefined || [\"Z\", \"X\", \"x\"].includes(state)) {\n throw new Error(`Failed to identify process ${String(pid)}`);\n }\n\n return { pid, startTime };\n};\n\nconst writeGuardCommand = (child: ChildProcess, operation: \"+\" | \"-\", job: GuardJob): void => {\n child.stdin?.write(`${operation}${JSON.stringify(job)}\\n`);\n};\n\nconst releaseGuard = (child: ChildProcess): void => {\n child.unref();\n const { stdin } = child;\n\n if (stdin instanceof Socket) {\n stdin.unref();\n }\n};\n\nconst isSameProcessWatch = (left: ProcessWatch, right: ProcessWatch): boolean =>\n left.owner.pid === right.owner.pid &&\n left.owner.startTime === right.owner.startTime &&\n left.target.pid === right.target.pid &&\n left.target.startTime === right.target.startTime;\n\nconst configureProcessWatch = (watch?: ProcessWatch): void => {\n if (watch === undefined) {\n return;\n }\n\n if (guard.watch !== undefined && !isSameProcessWatch(guard.watch, watch)) {\n throw new Error(\"The process guard is already watching another owner\");\n }\n\n if (guard.child !== undefined && guard.watch === undefined) {\n throw new Error(\"The process guard was started before its owner was registered\");\n }\n\n guard.watch = watch;\n};\n\nconst guardArguments = (): string[] =>\n guard.watch === undefined\n ? [GUARD_PATH, RUN_PREFIX]\n : [GUARD_PATH, RUN_PREFIX, JSON.stringify(guard.watch)];\n\nconst startGuard = (watch?: ProcessWatch): void => {\n configureProcessWatch(watch);\n\n if (guard.child) {\n return;\n }\n\n const child = spawn(process.execPath, guardArguments(), {\n detached: true,\n stdio: [\"pipe\", \"ignore\", \"ignore\"],\n });\n\n child.on(\"error\", () => {\n if (guard.child === child) {\n guard.child = undefined;\n }\n });\n\n child.on(\"exit\", () => {\n if (guard.child === child) {\n guard.child = undefined;\n }\n });\n\n child.stdin.on(\"error\", () => {\n if (guard.child === child) {\n guard.child = undefined;\n }\n });\n\n guard.child = child;\n\n for (const job of guard.jobs.values()) {\n writeGuardCommand(child, \"+\", job);\n }\n\n releaseGuard(child);\n};\n\nconst watchParentProcess = (): void => {\n const parentId = process.ppid;\n const watch = {\n owner: processIdentity(parentId),\n target: processIdentity(process.pid),\n };\n\n if (process.ppid !== parentId) {\n throw new Error(\"The parent process exited while its guard was starting\");\n }\n\n startGuard(watch);\n};\n\nconst registerJob = (job: GuardJob): void => {\n guard.jobs.set(job.marker, job);\n\n if (guard.child) {\n writeGuardCommand(guard.child, \"+\", job);\n }\n};\n\nconst unregisterJob = (job: GuardJob): void => {\n guard.jobs.delete(job.marker);\n\n if (guard.child) {\n writeGuardCommand(guard.child, \"-\", job);\n }\n};\n\nconst rollbackSpawn = ({ child, marker, processGroup, cleanupDirectories = [] }: SpawnRollback): void => {\n if (processGroup === undefined) {\n child.kill(\"SIGKILL\");\n } else {\n killProcessGroup(processGroup);\n }\n\n killMarkedProcesses(marker);\n\n for (const identity of cleanupDirectories) {\n removeCleanupDirectory(identity);\n }\n};\n\nconst captureCleanupDirectories = (command: string, paths: string[]): CleanupDirectoryIdentity[] => {\n const identities = paths.map((path) => cleanupDirectoryIdentity(path));\n\n if (identities.includes(undefined)) {\n throw new Error(`Failed to identify a cleanup directory for ${command}`);\n }\n\n return identities.filter((identity): identity is CleanupDirectoryIdentity => identity !== undefined);\n};\n\nconst spawnGuarded = (\n command: string,\n options: ParentDeathSpawnOptions,\n signal: GuardSignal,\n launchArguments: LaunchArguments,\n): ChildProcess => {\n const executable = resolveExecutable(command);\n const setpriv = resolveExecutable(\"setpriv\");\n const jobValue = `${RUN_ID}/${randomBytes(4).toString(\"hex\")}`;\n const marker = `${PROCESS_MARKER}=${jobValue}`;\n const cleanupDirectories = captureCleanupDirectories(command, options.cleanupDirectories ?? []);\n startGuard();\n\n const child = spawn(setpriv, launchArguments(executable, cleanupDirectories), {\n detached: true,\n stdio: options.stdio ?? \"ignore\",\n env: { ...(options.env ?? process.env), [PROCESS_MARKER]: jobValue },\n });\n\n const processGroupId = child.pid;\n const group = processGroupId === undefined ? undefined : processGroupIdentity(processGroupId);\n\n if (group === undefined) {\n rollbackSpawn({ child, marker, cleanupDirectories });\n throw new Error(`Failed to identify process group for ${command}`);\n }\n\n const job: GuardJob = { marker, processGroup: group, cleanupDirectories, signal };\n registerJob(job);\n\n child.on(\"exit\", () => {\n killMarkedProcesses(job.marker);\n unregisterJob(job);\n });\n\n return child;\n};\n\nfunction spawnWithParentDeathSignal(\n command: string,\n args: string[],\n options: ParentDeathSpawnOptions = {},\n): ChildProcess {\n return spawnGuarded(\n command,\n options,\n \"SIGKILL\",\n (executable) => [\"--pdeathsig\", \"SIGKILL\", executable, ...args],\n );\n}\n\nconst spawnWithParentDeathSupervisor = (\n command: string,\n args: string[],\n options: ParentDeathSupervisorOptions,\n): ChildProcess => {\n const shell = resolveExecutable(\"sh\");\n const stat = resolveExecutable(\"stat\");\n const rm = resolveExecutable(\"rm\");\n const setsid = resolveExecutable(\"setsid\");\n const sleep = resolveExecutable(\"sleep\");\n\n return spawnGuarded(\n command,\n { ...options, cleanupDirectories: [options.cleanupDirectory] },\n \"SIGCONT\",\n (executable, cleanupDirectories) => {\n const identity = cleanupDirectories[0];\n\n if (identity === undefined) {\n throw new Error(`Failed to identify a cleanup directory for ${command}`);\n }\n\n return [\n \"--pdeathsig\",\n \"SIGCONT\",\n shell,\n \"-c\",\n SUPERVISOR_SCRIPT,\n SUPERVISOR_NAME,\n identity.path,\n `${identity.device}:${identity.inode}:${identity.userId}`,\n String(process.pid),\n processIdentity(process.pid).startTime,\n stat,\n rm,\n shell,\n setsid,\n sleep,\n SUPERVISOR_WATCH_NAME,\n SUPERVISOR_WATCH_SCRIPT,\n SUPERVISOR_CLEANUP_NAME,\n SUPERVISOR_CLEANUP_SCRIPT,\n executable,\n ...args,\n ];\n },\n );\n};\n\nexport { spawnWithParentDeathSignal, spawnWithParentDeathSupervisor, watchParentProcess };\n"]}
|
|
1
|
+
{"version":3,"file":"spawn-with-parent-death-signal.js","sourceRoot":"","sources":["../../src/process/spawn-with-parent-death-signal.ts"],"names":[],"mappings":"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","sourcesContent":["import { type ChildProcess, spawn, type StdioOptions } from \"node:child_process\";\nimport { randomBytes } from \"node:crypto\";\nimport { readFileSync } from \"node:fs\";\nimport { Socket } from \"node:net\";\nimport { dirname, extname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { killMarkedProcesses, PROCESS_MARKER } from \"./kill-marked-processes.ts\";\nimport {\n type CleanupDirectoryIdentity,\n cleanupDirectoryIdentity,\n killProcessGroup,\n type ProcessGroupIdentity,\n processGroupIdentity,\n removeCleanupDirectory,\n} from \"./kill-process-group.ts\";\nimport { resolveExecutable } from \"./resolve-executable.ts\";\n\ntype ParentDeathSpawnOptions = {\n stdio?: StdioOptions;\n env?: NodeJS.ProcessEnv;\n cleanupDirectories?: string[];\n};\n\ntype ParentDeathSupervisorOptions = Omit<ParentDeathSpawnOptions, \"cleanupDirectories\"> & {\n cleanupDirectory: string;\n};\n\ntype GuardSignal = \"SIGKILL\" | \"SIGCONT\";\n\ntype ProcessIdentity = {\n pid: number;\n startTime: string;\n};\n\ntype ProcessWatch = {\n owner: ProcessIdentity;\n target: ProcessIdentity;\n};\n\ntype LaunchArguments = (executable: string, cleanupDirectories: CleanupDirectoryIdentity[]) => string[];\n\ntype GuardJob = {\n marker: string;\n processGroup: ProcessGroupIdentity;\n cleanupDirectories: CleanupDirectoryIdentity[];\n signal: GuardSignal;\n};\n\ntype GuardState = {\n child?: ChildProcess | undefined;\n jobs: Map<string, GuardJob>;\n watch?: ProcessWatch;\n};\n\ntype SpawnRollback = {\n child: ChildProcess;\n marker: string;\n processGroup?: ProcessGroupIdentity;\n cleanupDirectories?: CleanupDirectoryIdentity[];\n};\n\nconst MODULE_PATH = fileURLToPath(import.meta.url);\nconst GUARD_PATH = join(dirname(MODULE_PATH), `process-guard${extname(MODULE_PATH)}`);\nconst RUN_ID = randomBytes(8).toString(\"hex\");\nconst RUN_PREFIX = `${PROCESS_MARKER}=${RUN_ID}/`;\nconst guard: GuardState = { jobs: new Map() };\nconst SUPERVISOR_NAME = \"gtkx-process-supervisor\";\nconst SUPERVISOR_CLEANUP_NAME = \"gtkx-process-cleanup\";\nconst SUPERVISOR_WATCH_NAME = \"gtkx-process-watch\";\nconst SUPERVISOR_KILL_GROUP_BODY = [\n \"remaining=40\",\n 'while [ \"$remaining\" -gt 0 ] && kill -KILL \"-$group\" 2>/dev/null; do',\n ' \"$sleep_command\" 0.025',\n \" remaining=$((remaining - 1))\",\n \"done\",\n];\nconst SUPERVISOR_REMOVE_RUNTIME_BODY = [\n \"remaining=40\",\n 'while [ \"$remaining\" -gt 0 ] && ' +\n '[ \"$(\"$stat_command\" -c \"%d:%i:%u\" -- \"$runtime\" 2>/dev/null)\" = \"$identity\" ]; do',\n ' \"$rm_command\" -rf -- \"$runtime\"',\n ' \"$sleep_command\" 0.025',\n \" remaining=$((remaining - 1))\",\n \"done\",\n];\nconst SUPERVISOR_CLEANUP_BODY = [...SUPERVISOR_KILL_GROUP_BODY, ...SUPERVISOR_REMOVE_RUNTIME_BODY];\nconst SUPERVISOR_CLEANUP_SCRIPT = [\n \"runtime=$1\",\n \"identity=$2\",\n \"group=$3\",\n \"stat_command=$4\",\n \"rm_command=$5\",\n \"sleep_command=$6\",\n ...SUPERVISOR_CLEANUP_BODY,\n].join(\"\\n\");\nconst SUPERVISOR_WATCH_SCRIPT = [\n \"runtime=$1\",\n \"identity=$2\",\n \"group=$3\",\n \"group_start=$4\",\n \"expected_parent=$5\",\n \"expected_parent_start=$6\",\n \"stat_command=$7\",\n \"rm_command=$8\",\n \"sleep_command=$9\",\n \"matches_process() {\",\n \" expected_process=$1\",\n \" expected_start=$2\",\n \" process_stat=\",\n ' IFS= read -r process_stat < \"/proc/$expected_process/stat\" || return 1',\n \" process_tail=${process_stat##*) }\",\n \" set -- $process_tail\",\n ' case \"$1\" in Z|X|x) return 1 ;; esac',\n ' [ \"${20}\" = \"$expected_start\" ]',\n \"}\",\n \"matches_parent() {\",\n ' matches_process \"$expected_parent\" \"$expected_parent_start\"',\n \"}\",\n \"kill_group() {\",\n ...SUPERVISOR_KILL_GROUP_BODY.map((line) => ` ${line}`),\n \"}\",\n \"cleanup() {\",\n ' trap \"\" TERM INT HUP',\n \" kill_group\",\n ...SUPERVISOR_REMOVE_RUNTIME_BODY.map((line) => ` ${line}`),\n \" exit 0\",\n \"}\",\n \"trap cleanup TERM INT HUP\",\n 'while matches_process \"$group\" \"$group_start\" && matches_parent; do',\n ' \"$sleep_command\" 0.1',\n \"done\",\n \"kill_group\",\n \"while matches_parent; do\",\n ' \"$sleep_command\" 0.1',\n \"done\",\n \"cleanup\",\n].join(\"\\n\");\nconst SUPERVISOR_SCRIPT = [\n \"runtime=$1\",\n \"identity=$2\",\n \"expected_parent=$3\",\n \"expected_parent_start=$4\",\n \"stat_command=$5\",\n \"rm_command=$6\",\n \"shell_command=$7\",\n \"setsid_command=$8\",\n \"sleep_command=$9\",\n \"shift 9\",\n \"watch_name=$1\",\n \"watch_script=$2\",\n \"cleanup_name=$3\",\n \"cleanup_script=$4\",\n \"shift 4\",\n \"process_start() {\",\n \" process_stat=\",\n ' IFS= read -r process_stat < \"/proc/$1/stat\" || return 1',\n \" process_tail=${process_stat##*) }\",\n \" set -- $process_tail\",\n ' case \"$1\" in Z|X|x) return 1 ;; esac',\n ' printf \"%s\" \"${20}\"',\n \"}\",\n \"matches_parent() {\",\n \" parent_stat=\",\n ' IFS= read -r parent_stat < \"/proc/$expected_parent/stat\" || return 1',\n \" parent_tail=${parent_stat##*) }\",\n \" set -- $parent_tail\",\n ' case \"$1\" in Z|X|x) return 1 ;; esac',\n ' [ \"${20}\" = \"$expected_parent_start\" ]',\n \"}\",\n \"terminate() {\",\n ' trap \"\" CONT TERM INT HUP',\n \" while :; do\",\n ' \"$setsid_command\" \"$shell_command\" -c \"$cleanup_script\" \"$cleanup_name\" \"$runtime\" \"$identity\" \"$$\" ' +\n '\"$stat_command\" \"$rm_command\" \"$sleep_command\" </dev/null >/dev/null 2>&1 &',\n \" cleanup=$!\",\n ' wait \"$cleanup\" 2>/dev/null',\n ' \"$sleep_command\" 0.025',\n \" done\",\n \"}\",\n \"continue_or_terminate() {\",\n \" remaining=40\",\n ' while matches_parent && [ \"$remaining\" -gt 0 ]; do',\n ' \"$sleep_command\" 0.025',\n \" remaining=$((remaining - 1))\",\n \" done\",\n \" if ! matches_parent; then terminate; fi\",\n \"}\",\n \"trap continue_or_terminate CONT\",\n \"trap terminate TERM INT HUP\",\n \"supervisor_start=$(process_start \\\"$$\\\") || terminate\",\n '( unset GTKX_PROCESS_GUARD; exec \"$setsid_command\" \"$shell_command\" -c \"$watch_script\" \"$watch_name\" \"$runtime\" ' +\n '\"$identity\" \"$$\" \"$supervisor_start\" \"$expected_parent\" \"$expected_parent_start\" \"$stat_command\" ' +\n '\"$rm_command\" \"$sleep_command\" ) </dev/null >/dev/null 2>&1 &',\n \"child=\",\n \"if ! matches_parent; then terminate; fi\",\n '\"$@\" &',\n \"child=$!\",\n \"while :; do\",\n ' wait \"$child\"',\n \" status=$?\",\n ' if kill -0 \"$child\" 2>/dev/null; then continue; fi',\n ' exit \"$status\"',\n \"done\",\n].join(\"\\n\");\n\nconst processIdentity = (pid: number): ProcessIdentity => {\n const stat = readFileSync(`/proc/${String(pid)}/stat`, \"utf8\");\n const fields = stat.slice(stat.lastIndexOf(\") \") + 2).split(\" \", 20);\n const state = fields[0];\n const startTime = fields[19];\n\n if (startTime === undefined || state === undefined || [\"Z\", \"X\", \"x\"].includes(state)) {\n throw new Error(`Failed to identify process ${String(pid)}`);\n }\n\n return { pid, startTime };\n};\n\nconst writeGuardCommand = (child: ChildProcess, operation: \"+\" | \"-\", job: GuardJob): void => {\n child.stdin?.write(`${operation}${JSON.stringify(job)}\\n`);\n};\n\nconst releaseGuard = (child: ChildProcess): void => {\n child.unref();\n const { stdin } = child;\n\n if (stdin instanceof Socket) {\n stdin.unref();\n }\n};\n\nconst isSameProcessWatch = (left: ProcessWatch, right: ProcessWatch): boolean =>\n left.owner.pid === right.owner.pid &&\n left.owner.startTime === right.owner.startTime &&\n left.target.pid === right.target.pid &&\n left.target.startTime === right.target.startTime;\n\nconst configureProcessWatch = (watch?: ProcessWatch): void => {\n if (watch === undefined) {\n return;\n }\n\n if (guard.watch !== undefined && !isSameProcessWatch(guard.watch, watch)) {\n throw new Error(\"The process guard is already watching another owner\");\n }\n\n if (guard.child !== undefined && guard.watch === undefined) {\n throw new Error(\"The process guard was started before its owner was registered\");\n }\n\n guard.watch = watch;\n};\n\nconst guardArguments = (): string[] =>\n guard.watch === undefined\n ? [GUARD_PATH, RUN_PREFIX]\n : [GUARD_PATH, RUN_PREFIX, JSON.stringify(guard.watch)];\n\nconst startGuard = (watch?: ProcessWatch): void => {\n configureProcessWatch(watch);\n\n if (guard.child) {\n return;\n }\n\n const child = spawn(process.execPath, guardArguments(), {\n detached: true,\n stdio: [\"pipe\", \"ignore\", \"ignore\"],\n });\n\n child.on(\"error\", () => {\n if (guard.child === child) {\n guard.child = undefined;\n }\n });\n\n child.on(\"exit\", () => {\n if (guard.child === child) {\n guard.child = undefined;\n }\n });\n\n child.stdin.on(\"error\", () => {\n if (guard.child === child) {\n guard.child = undefined;\n }\n });\n\n guard.child = child;\n\n for (const job of guard.jobs.values()) {\n writeGuardCommand(child, \"+\", job);\n }\n\n releaseGuard(child);\n};\n\nconst watchParentProcess = (): void => {\n const parentId = process.ppid;\n const watch = {\n owner: processIdentity(parentId),\n target: processIdentity(process.pid),\n };\n\n if (process.ppid !== parentId) {\n throw new Error(\"The parent process exited while its guard was starting\");\n }\n\n startGuard(watch);\n};\n\nconst registerJob = (job: GuardJob): void => {\n guard.jobs.set(job.marker, job);\n\n if (guard.child) {\n writeGuardCommand(guard.child, \"+\", job);\n }\n};\n\nconst unregisterJob = (job: GuardJob): void => {\n guard.jobs.delete(job.marker);\n\n if (guard.child) {\n writeGuardCommand(guard.child, \"-\", job);\n }\n};\n\nconst rollbackSpawn = ({ child, marker, processGroup, cleanupDirectories = [] }: SpawnRollback): void => {\n if (processGroup === undefined) {\n child.kill(\"SIGKILL\");\n } else {\n killProcessGroup(processGroup);\n }\n\n killMarkedProcesses(marker);\n\n for (const identity of cleanupDirectories) {\n removeCleanupDirectory(identity);\n }\n};\n\nconst captureCleanupDirectories = (command: string, paths: string[]): CleanupDirectoryIdentity[] => {\n const identities = paths.map((path) => cleanupDirectoryIdentity(path));\n\n if (identities.includes(undefined)) {\n throw new Error(`Failed to identify a cleanup directory for ${command}`);\n }\n\n return identities.filter((identity): identity is CleanupDirectoryIdentity => identity !== undefined);\n};\n\nconst spawnGuarded = (\n command: string,\n options: ParentDeathSpawnOptions,\n signal: GuardSignal,\n launchArguments: LaunchArguments,\n): ChildProcess => {\n const executable = resolveExecutable(command);\n const setpriv = resolveExecutable(\"setpriv\");\n const jobValue = `${RUN_ID}/${randomBytes(4).toString(\"hex\")}`;\n const marker = `${PROCESS_MARKER}=${jobValue}`;\n const cleanupDirectories = captureCleanupDirectories(command, options.cleanupDirectories ?? []);\n startGuard();\n\n const child = spawn(setpriv, launchArguments(executable, cleanupDirectories), {\n detached: true,\n stdio: options.stdio ?? \"ignore\",\n env: { ...(options.env ?? process.env), [PROCESS_MARKER]: jobValue },\n });\n\n const processGroupId = child.pid;\n const group = processGroupId === undefined ? undefined : processGroupIdentity(processGroupId);\n\n if (group === undefined) {\n rollbackSpawn({ child, marker, cleanupDirectories });\n throw new Error(`Failed to identify process group for ${command}`);\n }\n\n const job: GuardJob = { marker, processGroup: group, cleanupDirectories, signal };\n registerJob(job);\n\n child.on(\"exit\", () => {\n killMarkedProcesses(job.marker);\n unregisterJob(job);\n });\n\n return child;\n};\n\nfunction spawnWithParentDeathSignal(\n command: string,\n args: string[],\n options: ParentDeathSpawnOptions = {},\n): ChildProcess {\n return spawnGuarded(\n command,\n options,\n \"SIGKILL\",\n (executable) => [\"--pdeathsig\", \"SIGKILL\", executable, ...args],\n );\n}\n\nconst spawnWithParentDeathSupervisor = (\n command: string,\n args: string[],\n options: ParentDeathSupervisorOptions,\n): ChildProcess => {\n const shell = resolveExecutable(\"sh\");\n const stat = resolveExecutable(\"stat\");\n const rm = resolveExecutable(\"rm\");\n const setsid = resolveExecutable(\"setsid\");\n const sleep = resolveExecutable(\"sleep\");\n\n return spawnGuarded(\n command,\n { ...options, cleanupDirectories: [options.cleanupDirectory] },\n \"SIGCONT\",\n (executable, cleanupDirectories) => {\n const identity = cleanupDirectories[0];\n\n if (identity === undefined) {\n throw new Error(`Failed to identify a cleanup directory for ${command}`);\n }\n\n return [\n \"--pdeathsig\",\n \"SIGCONT\",\n shell,\n \"-c\",\n SUPERVISOR_SCRIPT,\n SUPERVISOR_NAME,\n identity.path,\n `${identity.device}:${identity.inode}:${identity.userId}`,\n String(process.pid),\n processIdentity(process.pid).startTime,\n stat,\n rm,\n shell,\n setsid,\n sleep,\n SUPERVISOR_WATCH_NAME,\n SUPERVISOR_WATCH_SCRIPT,\n SUPERVISOR_CLEANUP_NAME,\n SUPERVISOR_CLEANUP_SCRIPT,\n executable,\n ...args,\n ];\n },\n );\n};\n\nexport { spawnWithParentDeathSignal, spawnWithParentDeathSupervisor, watchParentProcess };\n"]}
|
package/package.json
CHANGED
|
@@ -67,12 +67,14 @@ const guard: GuardState = { jobs: new Map() };
|
|
|
67
67
|
const SUPERVISOR_NAME = "gtkx-process-supervisor";
|
|
68
68
|
const SUPERVISOR_CLEANUP_NAME = "gtkx-process-cleanup";
|
|
69
69
|
const SUPERVISOR_WATCH_NAME = "gtkx-process-watch";
|
|
70
|
-
const
|
|
70
|
+
const SUPERVISOR_KILL_GROUP_BODY = [
|
|
71
71
|
"remaining=40",
|
|
72
72
|
'while [ "$remaining" -gt 0 ] && kill -KILL "-$group" 2>/dev/null; do',
|
|
73
73
|
' "$sleep_command" 0.025',
|
|
74
74
|
" remaining=$((remaining - 1))",
|
|
75
75
|
"done",
|
|
76
|
+
];
|
|
77
|
+
const SUPERVISOR_REMOVE_RUNTIME_BODY = [
|
|
76
78
|
"remaining=40",
|
|
77
79
|
'while [ "$remaining" -gt 0 ] && ' +
|
|
78
80
|
'[ "$("$stat_command" -c "%d:%i:%u" -- "$runtime" 2>/dev/null)" = "$identity" ]; do',
|
|
@@ -81,6 +83,7 @@ const SUPERVISOR_CLEANUP_BODY = [
|
|
|
81
83
|
" remaining=$((remaining - 1))",
|
|
82
84
|
"done",
|
|
83
85
|
];
|
|
86
|
+
const SUPERVISOR_CLEANUP_BODY = [...SUPERVISOR_KILL_GROUP_BODY, ...SUPERVISOR_REMOVE_RUNTIME_BODY];
|
|
84
87
|
const SUPERVISOR_CLEANUP_SCRIPT = [
|
|
85
88
|
"runtime=$1",
|
|
86
89
|
"identity=$2",
|
|
@@ -110,14 +113,24 @@ const SUPERVISOR_WATCH_SCRIPT = [
|
|
|
110
113
|
' case "$1" in Z|X|x) return 1 ;; esac',
|
|
111
114
|
' [ "${20}" = "$expected_start" ]',
|
|
112
115
|
"}",
|
|
116
|
+
"matches_parent() {",
|
|
117
|
+
' matches_process "$expected_parent" "$expected_parent_start"',
|
|
118
|
+
"}",
|
|
119
|
+
"kill_group() {",
|
|
120
|
+
...SUPERVISOR_KILL_GROUP_BODY.map((line) => ` ${line}`),
|
|
121
|
+
"}",
|
|
113
122
|
"cleanup() {",
|
|
114
123
|
' trap "" TERM INT HUP',
|
|
115
|
-
|
|
124
|
+
" kill_group",
|
|
125
|
+
...SUPERVISOR_REMOVE_RUNTIME_BODY.map((line) => ` ${line}`),
|
|
116
126
|
" exit 0",
|
|
117
127
|
"}",
|
|
118
128
|
"trap cleanup TERM INT HUP",
|
|
119
|
-
'while matches_process "$group" "$group_start" && '
|
|
120
|
-
'
|
|
129
|
+
'while matches_process "$group" "$group_start" && matches_parent; do',
|
|
130
|
+
' "$sleep_command" 0.1',
|
|
131
|
+
"done",
|
|
132
|
+
"kill_group",
|
|
133
|
+
"while matches_parent; do",
|
|
121
134
|
' "$sleep_command" 0.1',
|
|
122
135
|
"done",
|
|
123
136
|
"cleanup",
|