@descryy/runtime-controller 0.4.0 → 0.4.2
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.
- package/dist/attach-discovery.d.ts +26 -0
- package/dist/attach-discovery.d.ts.map +1 -1
- package/dist/attach-discovery.js +181 -10
- package/dist/attach-discovery.js.map +1 -1
- package/dist/attach-fencing.d.ts +11 -1
- package/dist/attach-fencing.d.ts.map +1 -1
- package/dist/attach-fencing.js +52 -23
- package/dist/attach-fencing.js.map +1 -1
- package/dist/attach-log-file.d.ts +23 -0
- package/dist/attach-log-file.d.ts.map +1 -0
- package/dist/attach-log-file.js +90 -0
- package/dist/attach-log-file.js.map +1 -0
- package/dist/bounded-file.d.ts +11 -0
- package/dist/bounded-file.d.ts.map +1 -0
- package/dist/bounded-file.js +41 -0
- package/dist/bounded-file.js.map +1 -0
- package/dist/bounded-output.d.ts +25 -0
- package/dist/bounded-output.d.ts.map +1 -0
- package/dist/bounded-output.js +95 -0
- package/dist/bounded-output.js.map +1 -0
- package/dist/container-sandbox.d.ts +7 -20
- package/dist/container-sandbox.d.ts.map +1 -1
- package/dist/container-sandbox.js +140 -8
- package/dist/container-sandbox.js.map +1 -1
- package/dist/controller.d.ts +10 -2
- package/dist/controller.d.ts.map +1 -1
- package/dist/controller.js +245 -84
- package/dist/controller.js.map +1 -1
- package/dist/dependency-version-check.d.ts +1 -0
- package/dist/dependency-version-check.d.ts.map +1 -1
- package/dist/dependency-version-check.js +43 -24
- package/dist/dependency-version-check.js.map +1 -1
- package/dist/environment-metadata.d.ts +13 -0
- package/dist/environment-metadata.d.ts.map +1 -1
- package/dist/environment-metadata.js +138 -24
- package/dist/environment-metadata.js.map +1 -1
- package/dist/environment-version-check.d.ts +1 -0
- package/dist/environment-version-check.d.ts.map +1 -1
- package/dist/environment-version-check.js +13 -7
- package/dist/environment-version-check.js.map +1 -1
- package/dist/execution-safety.d.ts +2 -0
- package/dist/execution-safety.d.ts.map +1 -1
- package/dist/execution-safety.js +36 -0
- package/dist/execution-safety.js.map +1 -1
- package/dist/index.d.ts +16 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -4
- package/dist/index.js.map +1 -1
- package/dist/node-options.d.ts +3 -0
- package/dist/node-options.d.ts.map +1 -0
- package/dist/node-options.js +34 -0
- package/dist/node-options.js.map +1 -0
- package/dist/orphan-reaper-process.d.ts +2 -0
- package/dist/orphan-reaper-process.d.ts.map +1 -0
- package/dist/orphan-reaper-process.js +98 -0
- package/dist/orphan-reaper-process.js.map +1 -0
- package/dist/orphan-reaper.d.ts +25 -0
- package/dist/orphan-reaper.d.ts.map +1 -0
- package/dist/orphan-reaper.js +161 -0
- package/dist/orphan-reaper.js.map +1 -0
- package/dist/process-identity.d.ts +1 -0
- package/dist/process-identity.d.ts.map +1 -1
- package/dist/process-identity.js +18 -4
- package/dist/process-identity.js.map +1 -1
- package/dist/process-manager.d.ts +13 -9
- package/dist/process-manager.d.ts.map +1 -1
- package/dist/process-manager.js +309 -133
- package/dist/process-manager.js.map +1 -1
- package/dist/readiness.d.ts +1 -0
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +77 -11
- package/dist/readiness.js.map +1 -1
- package/dist/sandbox.d.ts +22 -8
- package/dist/sandbox.d.ts.map +1 -1
- package/dist/sandbox.js +366 -51
- package/dist/sandbox.js.map +1 -1
- package/dist/spawn-environment.d.ts +16 -0
- package/dist/spawn-environment.d.ts.map +1 -0
- package/dist/spawn-environment.js +35 -0
- package/dist/spawn-environment.js.map +1 -0
- package/dist/target-pid.d.ts +6 -0
- package/dist/target-pid.d.ts.map +1 -0
- package/dist/target-pid.js +18 -0
- package/dist/target-pid.js.map +1 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
export { withDefaultProcessEnv } from "./env.js";
|
|
2
2
|
export { spawnProcess, attachManagedProcess, isProcessAlive } from "./process-manager.js";
|
|
3
|
+
export { resolveAttachLogPath, openAttachLogFile, DEFAULT_ATTACH_LOG_BACKLOG_CAP_BYTES } from "./attach-log-file.js";
|
|
4
|
+
export { assertTargetPid, targetPidRefusalReason } from "./target-pid.js";
|
|
5
|
+
export { buildChildEnvironment } from "./spawn-environment.js";
|
|
6
|
+
export { composeNodeOptions } from "./node-options.js";
|
|
3
7
|
export { computeAttachFence, getProcessStartTimeMs, detectOtherLogWriters } from "./attach-fencing.js";
|
|
4
8
|
export { READINESS_MECHANISMS, READINESS_IDENTITY_LEVELS, awaitReadiness, createProcessOutputReader } from "./readiness.js";
|
|
5
9
|
export { verifyListeningSocketOwner } from "./process-identity.js";
|
|
6
|
-
export { REAL_PROC_READER, findPortOwner, resolveLogSourceForPid } from "./attach-discovery.js";
|
|
10
|
+
export { REAL_KUBECTL, REAL_PROC_READER, findPortOwner, resolveKubernetesContainer, resolveLogSourceForPid } from "./attach-discovery.js";
|
|
11
|
+
export { orphanProtectionStatus, installOrphanSignalHandlers, terminateRegisteredGroups } from "./orphan-reaper.js";
|
|
7
12
|
export { ExecutionController } from "./controller.js";
|
|
8
13
|
export { createProcessCollector } from "./process-collector.js";
|
|
9
14
|
export { buildExecutionCapabilities, bestCapabilityStatus } from "./capability-registry.js";
|
|
10
|
-
export { resourceLimitCapability, applyResourceLimits, networkPolicyCapability, privilegeReportFor, currentPrivilegeReport, SANDBOX_BOUNDARY_DISCLOSURE, sandboxBoundaryDisclosureFor, ATTACH_MODE_SCOPE_DISCLOSURE, } from "./execution-safety.js";
|
|
11
|
-
export { filesystemIsolationCapability, networkIsolationCapability, unsupportedNetworkPolicyReason, resolveExecutableDirectory, applySandbox, } from "./sandbox.js";
|
|
15
|
+
export { resourceLimitCapability, applyResourceLimits, resourceLimitNotes, currentUserProcessCount, networkPolicyCapability, privilegeReportFor, currentPrivilegeReport, SANDBOX_BOUNDARY_DISCLOSURE, sandboxBoundaryDisclosureFor, ATTACH_MODE_SCOPE_DISCLOSURE, } from "./execution-safety.js";
|
|
16
|
+
export { filesystemIsolationCapability, networkIsolationCapability, unsupportedNetworkPolicyReason, resolveExecutableDirectory, applySandbox, sandboxPathRefusalReason, NO_SANDBOX_DISCLOSURES, SANDBOX_HOSTNAME, } from "./sandbox.js";
|
|
12
17
|
export { containerRuntimeCapability, containerFilesystemIsolationCapability, containerNetworkIsolationCapability, unsupportedContainerNetworkPolicyReason, resolveContainerImage, applyContainerSandbox, } from "./container-sandbox.js";
|
|
13
|
-
export { captureEnvironmentMetadata } from "./environment-metadata.js";
|
|
18
|
+
export { captureEnvironmentMetadata, resolveTrustedProbeExecutable } from "./environment-metadata.js";
|
|
14
19
|
export { checkDependencyVersions } from "./dependency-version-check.js";
|
|
15
20
|
export { DECLARED_VERSION_SOURCES, checkEnvironmentVersion, satisfiesDeclaredNodeVersion } from "./environment-version-check.js";
|
|
16
21
|
export { tokenizeCommand, validateServicesConfiguration, substitutePortPlaceholders } from "./orchestration.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG1F,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAevG,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAG5H,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAGnE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG1F,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,oCAAoC,EAAE,MAAM,sBAAsB,CAAC;AAGrH,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAG1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAevG,OAAO,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,cAAc,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAG5H,OAAO,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAGnE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAG1I,OAAO,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAGpH,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAG5F,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,2BAA2B,EAC3B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,8BAA8B,EAC9B,0BAA0B,EAC1B,YAAY,EACZ,wBAAwB,EACxB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,0BAA0B,EAC1B,sCAAsC,EACtC,mCAAmC,EACnC,uCAAuC,EACvC,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,0BAA0B,EAAE,6BAA6B,EAAE,MAAM,2BAA2B,CAAC;AAGtG,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAGxE,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAMjI,OAAO,EAAE,eAAe,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAYhH,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,0BAA0B,EAC1B,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,sBAAsB,EACtB,WAAW,GACZ,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-options.d.ts","sourceRoot":"","sources":["../src/node-options.ts"],"names":[],"mappings":"AA4BA,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,eAAe,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAG3G"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { isAbsolute } from "node:path";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
const MODULE_SPECIFIER_FLAGS = new Set(["--import", "--experimental-loader", "--loader"]);
|
|
4
|
+
function asModuleSpecifier(value) {
|
|
5
|
+
return isAbsolute(value) ? pathToFileURL(value).href : value;
|
|
6
|
+
}
|
|
7
|
+
function normalizeInterpreterArgs(args) {
|
|
8
|
+
const normalized = [];
|
|
9
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
10
|
+
const token = args[index];
|
|
11
|
+
const equals = token.indexOf("=");
|
|
12
|
+
if (equals > 0 && MODULE_SPECIFIER_FLAGS.has(token.slice(0, equals))) {
|
|
13
|
+
normalized.push(`${token.slice(0, equals)}=${asModuleSpecifier(token.slice(equals + 1))}`);
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
normalized.push(token);
|
|
17
|
+
const next = args[index + 1];
|
|
18
|
+
if (MODULE_SPECIFIER_FLAGS.has(token) && next !== undefined) {
|
|
19
|
+
normalized.push(asModuleSpecifier(next));
|
|
20
|
+
index += 1;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return normalized;
|
|
24
|
+
}
|
|
25
|
+
export function quoteNodeOptionToken(token) {
|
|
26
|
+
if (token !== "" && !/[\s"\\]/.test(token))
|
|
27
|
+
return token;
|
|
28
|
+
return `"${token.replace(/[\\"]/g, "\\$&")}"`;
|
|
29
|
+
}
|
|
30
|
+
export function composeNodeOptions(declared, interpreterArgs) {
|
|
31
|
+
const addition = normalizeInterpreterArgs(interpreterArgs).map(quoteNodeOptionToken).join(" ");
|
|
32
|
+
return declared === undefined || declared.trim() === "" ? addition : `${declared} ${addition}`;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=node-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-options.js","sourceRoot":"","sources":["../src/node-options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,sBAAsB,GAAwB,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,uBAAuB,EAAE,UAAU,CAAC,CAAC,CAAC;AAE/G,SAAS,iBAAiB,CAAC,KAAa;IACtC,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AAC/D,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAuB;IACvD,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,MAAM,GAAG,CAAC,IAAI,sBAAsB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;YACrE,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC3F,SAAS;QACX,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC7B,IAAI,sBAAsB,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC5D,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;YACzC,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;IACH,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,IAAI,KAAK,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACzD,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAA4B,EAAE,eAAkC;IACjG,MAAM,QAAQ,GAAG,wBAAwB,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/F,OAAO,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAC;AACjG,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orphan-reaper-process.d.ts","sourceRoot":"","sources":["../src/orphan-reaper-process.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
const TERMINATION_GRACE_MS = 3_000;
|
|
4
|
+
const POLL_INTERVAL_MS = 100;
|
|
5
|
+
const PRUNE_INTERVAL_MS = 1_000;
|
|
6
|
+
const CONTAINER_STOP_TIMEOUT_MS = 15_000;
|
|
7
|
+
const targets = new Map();
|
|
8
|
+
function groupAlive(pgid) {
|
|
9
|
+
try {
|
|
10
|
+
process.kill(-pgid, 0);
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
return error.code === "EPERM";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function signalGroup(pgid, signal) {
|
|
18
|
+
try {
|
|
19
|
+
process.kill(-pgid, signal);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function apply(message) {
|
|
26
|
+
if (message.op === "add")
|
|
27
|
+
targets.set(message.id, message.target);
|
|
28
|
+
else
|
|
29
|
+
targets.delete(message.id);
|
|
30
|
+
}
|
|
31
|
+
function parse(line) {
|
|
32
|
+
try {
|
|
33
|
+
const value = JSON.parse(line);
|
|
34
|
+
if (value.op === "remove" && typeof value.id === "number")
|
|
35
|
+
return { op: "remove", id: value.id };
|
|
36
|
+
if (value.op !== "add" || typeof value.id !== "number" || typeof value.target !== "object" || value.target === null)
|
|
37
|
+
return null;
|
|
38
|
+
const target = value.target;
|
|
39
|
+
if (target.kind === "group" && Number.isSafeInteger(target.pgid) && target.pgid > 1) {
|
|
40
|
+
return { op: "add", id: value.id, target: { kind: "group", pgid: target.pgid } };
|
|
41
|
+
}
|
|
42
|
+
if (target.kind === "container" && typeof target.name === "string" && target.name !== "") {
|
|
43
|
+
return { op: "add", id: value.id, target: { kind: "container", name: target.name } };
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function pruneVanishedGroups() {
|
|
52
|
+
for (const [id, target] of targets) {
|
|
53
|
+
if (target.kind === "group" && !groupAlive(target.pgid))
|
|
54
|
+
targets.delete(id);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function stopContainer(name) {
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
execFile("docker", ["stop", "--time", "2", name], { timeout: CONTAINER_STOP_TIMEOUT_MS }, () => resolve());
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async function reapEverything() {
|
|
63
|
+
const groups = [...targets.values()].flatMap((target) => (target.kind === "group" && groupAlive(target.pgid) ? [target.pgid] : []));
|
|
64
|
+
const containers = [...targets.values()].flatMap((target) => (target.kind === "container" ? [target.name] : []));
|
|
65
|
+
for (const pgid of groups)
|
|
66
|
+
signalGroup(pgid, "SIGTERM");
|
|
67
|
+
const stopping = Promise.all(containers.map(stopContainer));
|
|
68
|
+
const deadline = Date.now() + TERMINATION_GRACE_MS;
|
|
69
|
+
let remaining = groups;
|
|
70
|
+
while (remaining.length > 0 && Date.now() < deadline) {
|
|
71
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
72
|
+
remaining = remaining.filter(groupAlive);
|
|
73
|
+
}
|
|
74
|
+
for (const pgid of remaining)
|
|
75
|
+
signalGroup(pgid, "SIGKILL");
|
|
76
|
+
await stopping;
|
|
77
|
+
}
|
|
78
|
+
const pruner = setInterval(pruneVanishedGroups, PRUNE_INTERVAL_MS);
|
|
79
|
+
let reaping = false;
|
|
80
|
+
function onHostGone() {
|
|
81
|
+
if (reaping)
|
|
82
|
+
return;
|
|
83
|
+
reaping = true;
|
|
84
|
+
clearInterval(pruner);
|
|
85
|
+
void reapEverything().finally(() => process.exit(0));
|
|
86
|
+
}
|
|
87
|
+
const lines = createInterface({ input: process.stdin });
|
|
88
|
+
lines.on("line", (line) => {
|
|
89
|
+
const message = parse(line);
|
|
90
|
+
if (message !== null)
|
|
91
|
+
apply(message);
|
|
92
|
+
});
|
|
93
|
+
lines.on("close", onHostGone);
|
|
94
|
+
process.stdin.on("error", onHostGone);
|
|
95
|
+
for (const signal of ["SIGINT", "SIGHUP"])
|
|
96
|
+
process.on(signal, () => undefined);
|
|
97
|
+
process.on("SIGTERM", onHostGone);
|
|
98
|
+
//# sourceMappingURL=orphan-reaper-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orphan-reaper-process.js","sourceRoot":"","sources":["../src/orphan-reaper-process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAIhD,MAAM,oBAAoB,GAAG,KAAK,CAAC;AACnC,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAChC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEzC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;AAEhD,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAQ,KAA+B,CAAC,IAAI,KAAK,OAAO,CAAC;IAC3D,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,MAAsB;IACvD,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;AACH,CAAC;AAED,SAAS,KAAK,CAAC,OAAsB;IACnC,IAAI,OAAO,CAAC,EAAE,KAAK,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;;QAC7D,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,KAAK,CAAC,IAAY;IACzB,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA2B,CAAC;QACzD,IAAI,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ;YAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC;QACjG,IAAI,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACjI,MAAM,MAAM,GAAG,KAAK,CAAC,MAAoE,CAAC;QAC1F,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,IAAK,MAAM,CAAC,IAAe,GAAG,CAAC,EAAE,CAAC;YAChG,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAc,EAAE,EAAE,CAAC;QAC7F,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC;YACzF,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;QACvF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB;IAC1B,KAAK,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACnC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,OAAO,EAAE,yBAAyB,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7G,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpI,MAAM,UAAU,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjH,KAAK,MAAM,IAAI,IAAI,MAAM;QAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,oBAAoB,CAAC;IACnD,IAAI,SAAS,GAAG,MAAM,CAAC;IACvB,OAAO,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QACrD,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;QACtE,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,SAAS;QAAE,WAAW,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAC3D,MAAM,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,MAAM,GAAG,WAAW,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;AACnE,IAAI,OAAO,GAAG,KAAK,CAAC;AAEpB,SAAS,UAAU;IACjB,IAAI,OAAO;QAAE,OAAO;IACpB,OAAO,GAAG,IAAI,CAAC;IACf,aAAa,CAAC,MAAM,CAAC,CAAC;IACtB,KAAK,cAAc,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;AACxD,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;IACxB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,OAAO,KAAK,IAAI;QAAE,KAAK,CAAC,OAAO,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC;AACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC9B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACtC,KAAK,MAAM,MAAM,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAU;IAAE,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;AACxF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type OrphanTarget = {
|
|
2
|
+
readonly kind: "group";
|
|
3
|
+
readonly pgid: number;
|
|
4
|
+
} | {
|
|
5
|
+
readonly kind: "container";
|
|
6
|
+
readonly name: string;
|
|
7
|
+
};
|
|
8
|
+
export type ReaperMessage = {
|
|
9
|
+
readonly op: "add";
|
|
10
|
+
readonly id: number;
|
|
11
|
+
readonly target: OrphanTarget;
|
|
12
|
+
} | {
|
|
13
|
+
readonly op: "remove";
|
|
14
|
+
readonly id: number;
|
|
15
|
+
};
|
|
16
|
+
export interface OrphanProtectionStatus {
|
|
17
|
+
readonly state: "idle" | "active" | "degraded";
|
|
18
|
+
readonly reason: string | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function reaperEntryUrl(): URL;
|
|
21
|
+
export declare function terminateRegisteredGroups(graceMs?: number): void;
|
|
22
|
+
export declare function installOrphanSignalHandlers(signals?: readonly NodeJS.Signals[]): () => void;
|
|
23
|
+
export declare function orphanProtectionStatus(): OrphanProtectionStatus;
|
|
24
|
+
export declare function protectFromOrphaning(target: OrphanTarget): () => void;
|
|
25
|
+
//# sourceMappingURL=orphan-reaper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orphan-reaper.d.ts","sourceRoot":"","sources":["../src/orphan-reaper.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GAC1E;IAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IAC/C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wBAAgB,cAAc,IAAI,GAAG,CAIpC;AAyFD,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,MAAsB,GAAG,IAAI,CAU/E;AAUD,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,SAAS,MAAM,CAAC,OAAO,EAAoC,GAAG,MAAM,IAAI,CAe5H;AAED,wBAAgB,sBAAsB,IAAI,sBAAsB,CAS/D;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,IAAI,CAYrE"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
export function reaperEntryUrl() {
|
|
4
|
+
const self = import.meta.url;
|
|
5
|
+
const extension = self.endsWith(".ts") ? ".ts" : ".js";
|
|
6
|
+
return new URL(`./orphan-reaper-process${extension}`, self);
|
|
7
|
+
}
|
|
8
|
+
const EXIT_GRACE_MS = 1_000;
|
|
9
|
+
const EXIT_POLL_MS = 25;
|
|
10
|
+
const RESPAWN_AFTER_EXIT_MIN_INTERVAL_MS = 1_000;
|
|
11
|
+
const registered = new Map();
|
|
12
|
+
let nextId = 1;
|
|
13
|
+
let reaper = null;
|
|
14
|
+
let degradedReason = null;
|
|
15
|
+
let lastSpawnAttemptAt = 0;
|
|
16
|
+
let exitHookInstalled = false;
|
|
17
|
+
function send(message) {
|
|
18
|
+
const target = message.op === "add" ? ensureReaper() : liveReaper();
|
|
19
|
+
const stdin = target?.stdin;
|
|
20
|
+
if (stdin === null || stdin === undefined || stdin.destroyed)
|
|
21
|
+
return;
|
|
22
|
+
stdin.write(`${JSON.stringify(message)}\n`);
|
|
23
|
+
}
|
|
24
|
+
function liveReaper() {
|
|
25
|
+
return reaper !== null && reaper.exitCode === null && reaper.signalCode === null ? reaper : null;
|
|
26
|
+
}
|
|
27
|
+
function reaperArguments() {
|
|
28
|
+
const entry = fileURLToPath(reaperEntryUrl());
|
|
29
|
+
return entry.endsWith(".ts") ? ["--no-warnings", "--experimental-strip-types", entry] : ["--no-warnings", entry];
|
|
30
|
+
}
|
|
31
|
+
function ensureReaper() {
|
|
32
|
+
const live = liveReaper();
|
|
33
|
+
if (live !== null)
|
|
34
|
+
return live;
|
|
35
|
+
lastSpawnAttemptAt = Date.now();
|
|
36
|
+
let child;
|
|
37
|
+
try {
|
|
38
|
+
child = spawn(process.execPath, reaperArguments(), {
|
|
39
|
+
detached: true,
|
|
40
|
+
stdio: ["pipe", "ignore", "ignore"],
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
degradedReason = `the orphan reaper process could not be started: ${error instanceof Error ? error.message : String(error)}`;
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
child.on("error", (error) => {
|
|
48
|
+
degradedReason = `the orphan reaper process could not run: ${error.message}`;
|
|
49
|
+
if (reaper === child)
|
|
50
|
+
reaper = null;
|
|
51
|
+
});
|
|
52
|
+
child.once("exit", (code, signal) => {
|
|
53
|
+
if (reaper !== child)
|
|
54
|
+
return;
|
|
55
|
+
reaper = null;
|
|
56
|
+
if (registered.size === 0)
|
|
57
|
+
return;
|
|
58
|
+
degradedReason = `the orphan reaper process exited (${signal === null ? `code ${String(code)}` : `signal ${signal}`}) while ${String(registered.size)} process(es) were protected`;
|
|
59
|
+
if (Date.now() - lastSpawnAttemptAt >= RESPAWN_AFTER_EXIT_MIN_INTERVAL_MS)
|
|
60
|
+
ensureReaper();
|
|
61
|
+
});
|
|
62
|
+
child.stdin?.on("error", (error) => {
|
|
63
|
+
degradedReason = `the orphan reaper process stopped accepting registrations: ${error.message}`;
|
|
64
|
+
if (reaper === child)
|
|
65
|
+
reaper = null;
|
|
66
|
+
});
|
|
67
|
+
child.unref();
|
|
68
|
+
child.stdin?.unref?.();
|
|
69
|
+
reaper = child;
|
|
70
|
+
degradedReason = null;
|
|
71
|
+
for (const [id, target] of registered) {
|
|
72
|
+
child.stdin?.write(`${JSON.stringify({ op: "add", id, target })}\n`);
|
|
73
|
+
}
|
|
74
|
+
return child;
|
|
75
|
+
}
|
|
76
|
+
function sleepSynchronously(ms) {
|
|
77
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
78
|
+
}
|
|
79
|
+
function groupAlive(pgid) {
|
|
80
|
+
try {
|
|
81
|
+
process.kill(-pgid, 0);
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return error.code === "EPERM";
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function signalGroup(pgid, signal) {
|
|
89
|
+
try {
|
|
90
|
+
process.kill(-pgid, signal);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export function terminateRegisteredGroups(graceMs = EXIT_GRACE_MS) {
|
|
97
|
+
const groups = [...registered.values()].flatMap((target) => (target.kind === "group" ? [target.pgid] : []));
|
|
98
|
+
for (const pgid of groups)
|
|
99
|
+
signalGroup(pgid, "SIGTERM");
|
|
100
|
+
const deadline = Date.now() + graceMs;
|
|
101
|
+
let remaining = groups.filter(groupAlive);
|
|
102
|
+
while (remaining.length > 0 && Date.now() < deadline) {
|
|
103
|
+
sleepSynchronously(EXIT_POLL_MS);
|
|
104
|
+
remaining = remaining.filter(groupAlive);
|
|
105
|
+
}
|
|
106
|
+
for (const pgid of remaining)
|
|
107
|
+
signalGroup(pgid, "SIGKILL");
|
|
108
|
+
}
|
|
109
|
+
function installExitHook() {
|
|
110
|
+
if (exitHookInstalled)
|
|
111
|
+
return;
|
|
112
|
+
exitHookInstalled = true;
|
|
113
|
+
process.once("exit", () => {
|
|
114
|
+
terminateRegisteredGroups();
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
export function installOrphanSignalHandlers(signals = ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
118
|
+
const handlers = new Map();
|
|
119
|
+
for (const signal of signals) {
|
|
120
|
+
const handler = () => {
|
|
121
|
+
terminateRegisteredGroups();
|
|
122
|
+
for (const [installedSignal, installed] of handlers)
|
|
123
|
+
process.removeListener(installedSignal, installed);
|
|
124
|
+
process.kill(process.pid, signal);
|
|
125
|
+
};
|
|
126
|
+
handlers.set(signal, handler);
|
|
127
|
+
process.on(signal, handler);
|
|
128
|
+
}
|
|
129
|
+
return () => {
|
|
130
|
+
for (const [signal, handler] of handlers)
|
|
131
|
+
process.removeListener(signal, handler);
|
|
132
|
+
handlers.clear();
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
export function orphanProtectionStatus() {
|
|
136
|
+
if (registered.size === 0)
|
|
137
|
+
return { state: "idle", reason: null };
|
|
138
|
+
if (liveReaper() !== null)
|
|
139
|
+
return { state: "active", reason: null };
|
|
140
|
+
return {
|
|
141
|
+
state: "degraded",
|
|
142
|
+
reason: `${degradedReason ?? "the orphan reaper process is not running"}; ` +
|
|
143
|
+
"if this process is killed by SIGKILL or the OOM killer, the spawned processes and containers it started will keep running",
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
export function protectFromOrphaning(target) {
|
|
147
|
+
const id = nextId++;
|
|
148
|
+
registered.set(id, target);
|
|
149
|
+
installExitHook();
|
|
150
|
+
send({ op: "add", id, target });
|
|
151
|
+
let removed = false;
|
|
152
|
+
return () => {
|
|
153
|
+
if (removed)
|
|
154
|
+
return;
|
|
155
|
+
removed = true;
|
|
156
|
+
if (!registered.delete(id))
|
|
157
|
+
return;
|
|
158
|
+
send({ op: "remove", id });
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=orphan-reaper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orphan-reaper.js","sourceRoot":"","sources":["../src/orphan-reaper.ts"],"names":[],"mappings":"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"}
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
* readiness (every .NET managed-lifecycle test, found at release integration).
|
|
38
38
|
*/
|
|
39
39
|
export type IdentityVerification = "verified" | "mismatch" | "unsupported";
|
|
40
|
+
export declare function liveDescendantPids(root: number): readonly number[];
|
|
40
41
|
/**
|
|
41
42
|
* Does `expectedPid` -- or a process descended from it -- own the socket
|
|
42
43
|
* listening on `port`, on this host, right now? A real kernel-state check, not
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-identity.d.ts","sourceRoot":"","sources":["../src/process-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAIH,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,UAAU,GAAG,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"process-identity.d.ts","sourceRoot":"","sources":["../src/process-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAIH,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,UAAU,GAAG,aAAa,CAAC;AAiG3E,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAElE;AA6BD;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,oBAAoB,CAqBlG"}
|
package/dist/process-identity.js
CHANGED
|
@@ -91,16 +91,19 @@ function parentPidOf(pid) {
|
|
|
91
91
|
// afterName[0] is the state, afterName[1] the parent pid.
|
|
92
92
|
return afterName[1] ?? null;
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
const PROCESS_TABLE_TTL_MS = 500;
|
|
95
|
+
let cachedProcessTable = null;
|
|
96
|
+
function readChildrenMap(now, allowCached) {
|
|
97
|
+
if (allowCached && cachedProcessTable !== null && now - cachedProcessTable.takenAt < PROCESS_TABLE_TTL_MS)
|
|
98
|
+
return cachedProcessTable.childrenOf;
|
|
97
99
|
let entries;
|
|
98
100
|
try {
|
|
99
101
|
entries = readdirSync("/proc");
|
|
100
102
|
}
|
|
101
103
|
catch {
|
|
102
|
-
return
|
|
104
|
+
return null;
|
|
103
105
|
}
|
|
106
|
+
const childrenOf = new Map();
|
|
104
107
|
for (const entry of entries) {
|
|
105
108
|
if (!/^\d+$/.test(entry))
|
|
106
109
|
continue;
|
|
@@ -113,6 +116,14 @@ function processTree(root) {
|
|
|
113
116
|
else
|
|
114
117
|
siblings.push(entry);
|
|
115
118
|
}
|
|
119
|
+
cachedProcessTable = { takenAt: now, childrenOf };
|
|
120
|
+
return childrenOf;
|
|
121
|
+
}
|
|
122
|
+
/** `root` and every live process below it, from one pass over `/proc`'s parent-pid fields. */
|
|
123
|
+
function processTree(root, allowCached = true) {
|
|
124
|
+
const childrenOf = readChildrenMap(Date.now(), allowCached);
|
|
125
|
+
if (childrenOf === null)
|
|
126
|
+
return [String(root)];
|
|
116
127
|
const tree = [];
|
|
117
128
|
const pending = [String(root)];
|
|
118
129
|
const seen = new Set();
|
|
@@ -127,6 +138,9 @@ function processTree(root) {
|
|
|
127
138
|
}
|
|
128
139
|
return tree;
|
|
129
140
|
}
|
|
141
|
+
export function liveDescendantPids(root) {
|
|
142
|
+
return processTree(root, false).slice(1).map(Number);
|
|
143
|
+
}
|
|
130
144
|
/** Whether `pid`'s fd table holds one of `inodes`; `null` when that table cannot be read at all. */
|
|
131
145
|
function ownsOneOf(pid, inodes) {
|
|
132
146
|
let fds;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-identity.js","sourceRoot":"","sources":["../src/process-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAIlE,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,uIAAuI;AACvI,SAAS,mBAAmB,CAAC,IAAY;IACvC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,gBAAgB,GAAG,IAAI,CAAC;IAE9B,KAAK,MAAM,IAAI,IAAI,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAE,CAAC;QACvD,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;YACxE,yEAAyE;YACzE,SAAS;QACX,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACxC,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACxB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,YAAY,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;gBAAE,SAAS;YACvF,IAAI,KAAK,KAAK,gBAAgB;gBAAE,SAAS;YACzC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,IAAI,OAAO,KAAK,UAAU;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH;;+CAE+C;AAC/C,SAAS,WAAW,CAAC,GAAW;IAC9B,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,SAAS,GAAG,OAAO,EAAE,MAAM,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnE,0DAA0D;IAC1D,OAAO,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"process-identity.js","sourceRoot":"","sources":["../src/process-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAIlE,SAAS,OAAO,CAAC,IAAY;IAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AAC1D,CAAC;AAED,uIAAuI;AACvI,SAAS,mBAAmB,CAAC,IAAY;IACvC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;IACjC,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,gBAAgB,GAAG,IAAI,CAAC;IAE9B,KAAK,MAAM,IAAI,IAAI,CAAC,eAAe,EAAE,gBAAgB,CAAC,EAAE,CAAC;QACvD,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;YACP,wEAAwE;YACxE,yEAAyE;YACzE,SAAS;QACX,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACxC,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACxB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,YAAY,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,SAAS;gBAAE,SAAS;YACvF,IAAI,KAAK,KAAK,gBAAgB;gBAAE,SAAS;YACzC,MAAM,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,IAAI,OAAO,KAAK,UAAU;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH;;+CAE+C;AAC/C,SAAS,WAAW,CAAC,GAAW;IAC9B,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,SAAS,GAAG,OAAO,EAAE,MAAM,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnE,0DAA0D;IAC1D,OAAO,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAEjC,IAAI,kBAAkB,GAAqG,IAAI,CAAC;AAEhI,SAAS,eAAe,CAAC,GAAW,EAAE,WAAoB;IACxD,IAAI,WAAW,IAAI,kBAAkB,KAAK,IAAI,IAAI,GAAG,GAAG,kBAAkB,CAAC,OAAO,GAAG,oBAAoB;QAAE,OAAO,kBAAkB,CAAC,UAAU,CAAC;IAChJ,IAAI,OAAiB,CAAC;IACtB,IAAI,CAAC;QACH,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC/C,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;YAAE,SAAS;QACnC,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;QAClC,IAAI,MAAM,KAAK,IAAI;YAAE,SAAS;QAC9B,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,QAAQ,KAAK,SAAS;YAAE,UAAU,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;;YACvD,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IACD,kBAAkB,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;IAClD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,8FAA8F;AAC9F,SAAS,WAAW,CAAC,IAAY,EAAE,WAAW,GAAG,IAAI;IACnD,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;IAC5D,IAAI,UAAU,KAAK,IAAI;QAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/C,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAG,CAAC;QAC3B,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACf,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,OAAO,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACvD,CAAC;AAED,oGAAoG;AACpG,SAAS,SAAS,CAAC,GAAW,EAAE,MAA2B;IACzD,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,WAAW,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,oCAAoC;QACpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,iBAAiB,GAAG,oBAAoB,CAAC;IAC/C,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACrB,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,YAAY,CAAC,SAAS,GAAG,OAAO,EAAE,EAAE,CAAC,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,uEAAuE;YACvE,6CAA6C;YAC7C,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;YAAE,OAAO,IAAI,CAAC;IAC3D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAAY,EAAE,WAAmB;IAC1E,MAAM,MAAM,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACtB,kEAAkE;QAClE,uEAAuE;QACvE,gDAAgD;QAChD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,yEAAyE;IACzE,iDAAiD;IACjD,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;IACnD,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,aAAa,CAAC;IACvC,IAAI,GAAG;QAAE,OAAO,UAAU,CAAC;IAE3B,0EAA0E;IAC1E,0DAA0D;IAC1D,KAAK,MAAM,GAAG,IAAI,WAAW,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QACpD,IAAI,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,IAAI;YAAE,OAAO,UAAU,CAAC;IACzD,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
* fixture-app slice (§34).
|
|
8
8
|
*/
|
|
9
9
|
import type { FilesystemPolicy, NetworkPolicy, ProcessHandle, ResourceLimits, ServiceAttachConfiguration } from "@descryy/runtime-contracts";
|
|
10
|
+
import { type SandboxDisclosures } from "./sandbox.ts";
|
|
10
11
|
import { type AttachFence } from "./attach-fencing.ts";
|
|
12
|
+
import { type HostEnvironmentDisclosure } from "./spawn-environment.ts";
|
|
13
|
+
import { type ProcessOutputInfo, type ProcessOutputRead } from "./bounded-output.ts";
|
|
14
|
+
export type { ProcessOutputInfo, ProcessOutputRead } from "./bounded-output.ts";
|
|
11
15
|
/**
|
|
12
16
|
* Binds port 0, reads it, releases immediately. A real gap remains between "free
|
|
13
17
|
* when checked" and "still free when the child binds it" (RT-024's gap, one layer
|
|
@@ -48,6 +52,7 @@ export interface SpawnProcessOptions {
|
|
|
48
52
|
* Disclosed in `container-sandbox.ts`, not silently dropped.
|
|
49
53
|
*/
|
|
50
54
|
readonly sandboxBackend?: "bwrap" | "container";
|
|
55
|
+
readonly inheritHostEnvironment?: boolean;
|
|
51
56
|
}
|
|
52
57
|
export interface ProcessExitInfo {
|
|
53
58
|
readonly exitCode: number | null;
|
|
@@ -70,6 +75,7 @@ export interface ManagedProcess {
|
|
|
70
75
|
readOutput(): string;
|
|
71
76
|
/** Real total bytes seen and whether `readOutput()` is a truncated view of them (RT-261). */
|
|
72
77
|
outputInfo(): ProcessOutputInfo;
|
|
78
|
+
readOutputFrom(cursor: number): ProcessOutputRead;
|
|
73
79
|
waitForExit(): Promise<ProcessExitInfo>;
|
|
74
80
|
/** SIGTERM the process group, wait up to `gracePeriodMs`, then SIGKILL. Idempotent. */
|
|
75
81
|
kill(gracePeriodMs?: number): Promise<void>;
|
|
@@ -87,12 +93,9 @@ export interface ManagedProcess {
|
|
|
87
93
|
* `computeAttachFence` (`attach-fencing.ts`) for what it records and why.
|
|
88
94
|
*/
|
|
89
95
|
attachFence(): AttachFence | null;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
readonly totalBytesSeen: number;
|
|
94
|
-
/** True once `totalBytesSeen` exceeds what head+tail can hold -- `readOutput()` is a bounded view, not the whole thing. */
|
|
95
|
-
readonly truncated: boolean;
|
|
96
|
+
sandboxDisclosures(): SandboxDisclosures;
|
|
97
|
+
hostEnvironment?(): HostEnvironmentDisclosure | null;
|
|
98
|
+
resourceLimitNotes?(): readonly string[];
|
|
96
99
|
}
|
|
97
100
|
export declare function spawnProcess(options: SpawnProcessOptions): ManagedProcess;
|
|
98
101
|
/**
|
|
@@ -109,11 +112,12 @@ export interface AttachProcessOptions {
|
|
|
109
112
|
readonly attach: ServiceAttachConfiguration;
|
|
110
113
|
readonly serviceName?: string;
|
|
111
114
|
readonly port?: number;
|
|
115
|
+
readonly maxBacklogBytes?: number;
|
|
112
116
|
}
|
|
113
117
|
/**
|
|
114
|
-
* `ManagedProcess` for a service attached to rather than spawned.
|
|
115
|
-
* `attach.logFilePath`
|
|
116
|
-
*
|
|
118
|
+
* `ManagedProcess` for a service attached to rather than spawned. Tails
|
|
119
|
+
* `attach.logFilePath` from the last byte read into the same bounded head/tail
|
|
120
|
+
* buffer a spawned process uses, so a large log is read once, not on every poll.
|
|
117
121
|
*
|
|
118
122
|
* **`kill()` is a deliberate no-op, not a stub.** Descry did not spawn this process,
|
|
119
123
|
* and `ATTACH_MODE_SCOPE_DISCLOSURE` is unconditional: attach mode never executes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../src/process-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"process-manager.d.ts","sourceRoot":"","sources":["../src/process-manager.ts"],"names":[],"mappings":"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"}
|