@jigging/jig 0.1.0-alpha.25 → 0.1.0-alpha.27

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.
@@ -20,6 +20,7 @@ var POLICY = Object.freeze(["--no-env-file", "--no-install", "--config=/dev/null
20
20
  var SANDBOX_BUN = "/jig-runtime/bun";
21
21
  var SANDBOX_LIBRARY_PATH = "/jig-runtime/lib";
22
22
  var MAX_CONTROL_BYTES = 64 * 1024;
23
+ var CORE_DUMP_POLL_MS = 250;
23
24
  var MODULE_DESTINATION = "/jig/linux-rootless-supervisor.ts";
24
25
  var DIGEST = /^sha256:[0-9a-f]{64}$/;
25
26
  var OWNER_TOKEN = /^[0-9a-f]{64}$/;
@@ -112,6 +113,9 @@ async function superviseConnected(control, startupDeadlineUnixMs) {
112
113
  let exitSignal = null;
113
114
  let evidence = emptyEvidence();
114
115
  let terminal;
116
+ let coreDumpTimer;
117
+ let coreDumpCheck;
118
+ let monitoringClosed = false;
115
119
  try {
116
120
  await mkdir(runCgroup, { mode: 493 });
117
121
  cgroupCreated = true;
@@ -162,6 +166,19 @@ async function superviseConnected(control, startupDeadlineUnixMs) {
162
166
  });
163
167
  childExit = childClose(launched);
164
168
  child = launched;
169
+ coreDumpTimer = setInterval(() => {
170
+ if (monitoringClosed || stopReason !== undefined || coreDumpCheck !== undefined)
171
+ return;
172
+ coreDumpCheck = privateHasCoreDumpingProcess(runCgroup, limits.pids).then((dumping) => {
173
+ if (dumping && !monitoringClosed && stopReason === undefined)
174
+ stop("core_dump");
175
+ }).catch(() => {
176
+ if (!monitoringClosed && stopReason === undefined)
177
+ stop("setup_failed");
178
+ }).finally(() => {
179
+ coreDumpCheck = undefined;
180
+ });
181
+ }, CORE_DUMP_POLL_MS);
165
182
  launched.stdio[4].on("error", () => stop("setup_failed"));
166
183
  const ready = await readReady(launched);
167
184
  if (configuration.output) {
@@ -187,12 +204,16 @@ async function superviseConnected(control, startupDeadlineUnixMs) {
187
204
  process.stderr.write(`${errorText(error)}
188
205
  `);
189
206
  } finally {
207
+ monitoringClosed = true;
208
+ clearInterval(coreDumpTimer);
190
209
  clearTimeout(deadline);
191
210
  await outputDirectory?.close();
192
211
  let cleanupError;
193
212
  try {
194
213
  child?.kill("SIGKILL");
195
214
  await killRun();
215
+ if (coreDumpCheck !== undefined)
216
+ await withinTimeout(coreDumpCheck, limits.cleanupTimeoutMs, "core-dump check did not settle");
196
217
  if (childExit !== undefined) {
197
218
  await withinTimeout(childExit.catch(() => {
198
219
  return;
@@ -225,6 +246,36 @@ async function superviseConnected(control, startupDeadlineUnixMs) {
225
246
  control.end();
226
247
  }
227
248
  }
249
+ async function privateHasCoreDumpingProcess(runCgroup, maxProcesses, readText = (path) => readFile(path, "utf8")) {
250
+ const processes = (await readText(`${runCgroup}/cgroup.procs`)).trim();
251
+ const pids = processes === "" ? [] : processes.split(`
252
+ `);
253
+ if (!positiveInteger(maxProcesses) || pids.length > maxProcesses || pids.some((pid) => !/^[1-9][0-9]*$/.test(pid) || !Number.isSafeInteger(Number(pid))))
254
+ throw new Error("invalid owned process observation");
255
+ const membership = `0::${runCgroup.slice("/sys/fs/cgroup".length)}`;
256
+ for (const pid of pids) {
257
+ try {
258
+ const status = await readText(`/proc/${pid}/status`);
259
+ if (status.length > MAX_CONTROL_BYTES)
260
+ throw new Error("oversized owned process status");
261
+ if (!/^CoreDumping:/m.test(status))
262
+ continue;
263
+ const dumping = /^CoreDumping:[ \t]+([01])$/m.exec(status);
264
+ if (dumping === null)
265
+ throw new Error("kernel core-dump observation is unavailable");
266
+ if (dumping[1] !== "1")
267
+ continue;
268
+ if ((await readText(`/proc/${pid}/cgroup`)).split(`
269
+ `).includes(membership))
270
+ return true;
271
+ } catch (error) {
272
+ const code = error.code;
273
+ if (code !== "ENOENT" && code !== "ESRCH")
274
+ throw error;
275
+ }
276
+ }
277
+ return false;
278
+ }
228
279
  async function enterMain(arguments_) {
229
280
  requireFixedBunPosture("entry trampoline");
230
281
  if (arguments_.length < 7)
@@ -792,3 +843,6 @@ if (import.meta.main) {
792
843
  process.exitCode = 70;
793
844
  });
794
845
  }
846
+ export {
847
+ privateHasCoreDumpingProcess
848
+ };
Binary file