Skip to content

SessionTree.readProcs uses macOS-only ps flags and throws on Linux #2470

Open

Description

@jackmaninov

Version

LifeOS 8.761.0 · attestation: not run

What is broken

SessionTree.readProcs() reads the process table with macOS-only ps flags, so on Linux it throws before returning anything:

Error: Command failed: ps -ww -Axo pid=,ppid=,tty=,etime=,command=
error: must set personality to get -x option

procps-ng rejects BSD -x after a dash (-Axo), and it has no -E for the environment table either (ps -ww -E -Axo pid=,command= → unsupported SysV option). Every caller of readProcs() fails on Linux as a result. The visible one is the LifeOSHooks plugin's session-tree bridge, which logs the error on every pass once the plugin arms. RunningScan, OrphanReaper, HookBridge and Vigil's running adapter go through the same function.

Every other ps call in the tree runs fine on Linux (-o etime= -p, -o command= -p, -axo pid=,ppid=). psOne's -E call only runs on the darwin libc path, so it doesn't fail. The only failing site is the pair at SessionTree.ts:206-207.

Where (file:line)

LIFEOS/TOOLS/SessionTree.ts:206

Repro on a clean tree

# Linux, procps-ng 4.0.4, from the install root:
bun -e 'const m = await import("./LIFEOS/TOOLS/SessionTree.ts"); console.log(m.readProcs().length)'
# → Error: Command failed: ps -ww -Axo pid=,ppid=,tty=,etime=,command=

# the call on its own:
ps -ww -Axo pid=,ppid=,tty=,etime=,command=
# → error: must set personality to get -x option (exit 1)

Negative control

Probe: ps -ww -Axo pid=,ppid=,tty=,etime=,command= · exit 1 · captured 2026-10-30T09:01:14.546Z

Red looks like: must set personality

error: must set personality to get -x option

Usage:
 ps [options]

 Try 'ps --help <simple|list|output|threads|misc|all>'
  or 'ps --help <s|l|o|t|m|a>'
 for additional help text.

For more details see ps(1).

Suggested fix

On Linux, use -eo for the plain table and the BSD-style e modifier for the environment table (ps axeww -o pid=,command=). procps appends the environment after the command, as macOS -E does, so parseTables reads both tables unchanged. macOS keeps the current flags. We've run this locally since v8.761.0: readProcs() returns 921 processes, and the env-derived fields come back populated (84 with session, 171 with term). The patch is attached.

diff --git a/LIFEOS/TOOLS/SessionTree.ts b/LIFEOS/TOOLS/SessionTree.ts
index 6667c6d7..6d7dee0e 100644
--- a/LIFEOS/TOOLS/SessionTree.ts
+++ b/LIFEOS/TOOLS/SessionTree.ts
@@ -203,8 +203,11 @@ export function readProcs(): Proc[] {
 
 export function readProcsPs(): Proc[] {
   const opts = { encoding: "utf8" as const, maxBuffer: 64 * 1024 * 1024, stdio: ["ignore", "pipe", "ignore"] as ["ignore", "pipe", "ignore"] };
-  const plain = execFileSync("ps", ["-ww", "-Axo", "pid=,ppid=,tty=,etime=,command="], opts);
-  const env = execFileSync("ps", ["-ww", "-E", "-Axo", "pid=,command="], opts);
+  // Linux procps rejects BSD `-x` after a dash and has no `-E`; its BSD-style `e` modifier appends the
+  // environment after the command the same way, so parseTables reads both tables unchanged.
+  const linux = process.platform === "linux";
+  const plain = execFileSync("ps", linux ? ["-ww", "-eo", "pid=,ppid=,tty=,etime=,command="] : ["-ww", "-Axo", "pid=,ppid=,tty=,etime=,command="], opts);
+  const env = execFileSync("ps", linux ? ["axeww", "-o", "pid=,command="] : ["-ww", "-E", "-Axo", "pid=,command="], opts);
   return parseTables(plain, env);
 }

Environment

  • OS: Pop!_OS 24.04 LTS (x64)
  • Harness: claude-code
  • bun: 1.3.14 · git: 2.56.0
  • Doctor broken: none

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions