{"record":{"id":"8c1ff2b2de42cbba","repo":"can1357/oh-my-pi","slug":"failed-to-become-a-linux-child-subreaper","errorCode":null,"errorMessage":"failed to become a Linux child subreaper","messagePattern":"failed to become a Linux child subreaper","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/utils/src/ptree.ts","lineNumber":50,"sourceCode":"for (const soname of ${JSON.stringify(libcCandidates)}) {\n\ttry {\n\t\tlibc = dlopen(soname, {\n\t\t\tprctl: {\n\t\t\t\targs: [FFIType.i32, FFIType.u64, FFIType.u64, FFIType.u64, FFIType.u64],\n\t\t\t\treturns: FFIType.i32,\n\t\t\t},\n\t\t\twaitpid: {\n\t\t\t\targs: [FFIType.i32, FFIType.ptr, FFIType.i32],\n\t\t\t\treturns: FFIType.i32,\n\t\t\t},\n\t\t});\n\t\tbreak;\n\t} catch {}\n}\nif (!libc) throw new Error(\"failed to load libc for Linux child supervision\");\n\nif (libc.symbols.prctl(36, 1, 0, 0, 0) !== 0) {\n\tthrow new Error(\"failed to become a Linux child subreaper\");\n}\n\nconst commandJson = Bun.env.${LINUX_SUBREAPER_COMMAND_ENV};\nif (!commandJson) throw new Error(\"missing supervised command\");\nconst callerBunBeBun = Bun.env.${LINUX_SUBREAPER_BUN_BE_BUN_ENV};\ndelete Bun.env.${LINUX_SUBREAPER_COMMAND_ENV};\ndelete Bun.env.${LINUX_SUBREAPER_BUN_BE_BUN_ENV};\nif (callerBunBeBun === undefined) delete Bun.env.BUN_BE_BUN;\nelse Bun.env.BUN_BE_BUN = callerBunBeBun;\nconst command = JSON.parse(commandJson);\nconst child = Bun.spawn(command, {\n\tstdin: \"inherit\",\n\tstdout: \"pipe\",\n\tstderr: \"pipe\",\n\twindowsHide: true,\n\tenv: Bun.env,\n});\n","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ptree.ts#L32-L68","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the seccomp/sandbox profile and allow prctl (syscall 157 on x86_64).","Run the process outside the restricting sandbox (e.g. without gVisor) to confirm the cause.","If the platform cannot support subreapers, use a supervision mode that does not require the subreaper worker."],"exampleFix":"// docker run before (default restrictive profile)\ndocker run --security-opt seccomp=hardened.json ...\n// after\ndocker run --security-opt seccomp=profile-that-allows-prctl.json ...","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await runSupervised(cmd);\n} catch (err) {\n  if (String(err.message).includes('child subreaper')) {\n    logger.warn('subreaper unavailable; sandbox blocks prctl', { err });\n    // degrade to unsupervised spawn or fail fast with a clear message\n  } else throw err;\n}","preventionTips":["Audit seccomp/gVisor profiles for prctl (syscall 157) allowlisting before deploying.","Test supervised spawns inside the actual sandbox/CI environment, not just locally.","Document sandbox requirements for the deployment target."],"tags":["linux","prctl","subreaper","sandbox"],"backgroundTag":"prctl-not-permitted","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}