can1357/oh-my-pi · critical

failed to become a Linux child subreaper

Error message

failed to become a Linux child subreaper

What it means

The subreaper worker successfully loaded libc and called prctl(36 /* PR_SET_CHILD_SUBREAPER */, 1, 0, 0, 0), but the kernel returned non-zero, so the process could not be registered as a child subreaper. ptree throws rather than supervising without reaping ability, since orphaned grandchildren would be left untracked.

Source

Thrown at packages/utils/src/ptree.ts:50

for (const soname of ${JSON.stringify(libcCandidates)}) {
	try {
		libc = dlopen(soname, {
			prctl: {
				args: [FFIType.i32, FFIType.u64, FFIType.u64, FFIType.u64, FFIType.u64],
				returns: FFIType.i32,
			},
			waitpid: {
				args: [FFIType.i32, FFIType.ptr, FFIType.i32],
				returns: FFIType.i32,
			},
		});
		break;
	} catch {}
}
if (!libc) throw new Error("failed to load libc for Linux child supervision");

if (libc.symbols.prctl(36, 1, 0, 0, 0) !== 0) {
	throw new Error("failed to become a Linux child subreaper");
}

const commandJson = Bun.env.${LINUX_SUBREAPER_COMMAND_ENV};
if (!commandJson) throw new Error("missing supervised command");
const callerBunBeBun = Bun.env.${LINUX_SUBREAPER_BUN_BE_BUN_ENV};
delete Bun.env.${LINUX_SUBREAPER_COMMAND_ENV};
delete Bun.env.${LINUX_SUBREAPER_BUN_BE_BUN_ENV};
if (callerBunBeBun === undefined) delete Bun.env.BUN_BE_BUN;
else Bun.env.BUN_BE_BUN = callerBunBeBun;
const command = JSON.parse(commandJson);
const child = Bun.spawn(command, {
	stdin: "inherit",
	stdout: "pipe",
	stderr: "pipe",
	windowsHide: true,
	env: Bun.env,
});

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect the seccomp/sandbox profile and allow prctl (syscall 157 on x86_64).
  2. Run the process outside the restricting sandbox (e.g. without gVisor) to confirm the cause.
  3. If the platform cannot support subreapers, use a supervision mode that does not require the subreaper worker.

Example fix

// docker run before (default restrictive profile)
docker run --security-opt seccomp=hardened.json ...
// after
docker run --security-opt seccomp=profile-that-allows-prctl.json ...
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await runSupervised(cmd);
} catch (err) {
  if (String(err.message).includes('child subreaper')) {
    logger.warn('subreaper unavailable; sandbox blocks prctl', { err });
    // degrade to unsupervised spawn or fail fast with a clear message
  } else throw err;
}

Prevention

When it happens

Trigger: prctl(PR_SET_CHILD_SUBREAPER) returning non-zero — practically only in restricted environments: seccomp/LSM filters blocking prctl (some sandboxes, gVisor, hardened containers), or running under an emulator/OS where prctl(36) is not implemented.

Common situations: Containers with restrictive seccomp profiles (Docker default profiles usually allow prctl, but custom hardened ones may not), gVisor/runsc sandboxes, CI runners with syscall filtering.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/8c1ff2b2de42cbba. Report an issue: GitHub.