stablyai/orca · error · Error

Owned X11 session processes survived cleanup

Error message

Owned X11 session processes survived cleanup: ${remaining.join('; ')}

What it means

After the inner session exits, runOuter() calls stopOwnedProcessGroup(sessionProcess.pid) to reap the whole xvfb-run tree (Xvfb, the inner session's IBus, xfwm4, etc.). Survivors would leak X servers and DBus daemons onto the host. The surviving PID list is included in the message.

Solutions

  1. Inspect the surviving PIDs (the message lists them) and identify which component escapes.
  2. Run the outer harness inside a PID namespace so xvfb-run's entire tree is reaped on session exit.
  3. Disable DBus/session autostart of ibus and other helpers inside the inner session env.
  4. Ensure stopOwnedProcessGroup escalates to SIGKILL and re-checks for the session group.

Example fix

// before
pnpm run test:e2e:terminal-ibus-hangul-native
// after
unshare -p --fork --mount-proc pnpm run test:e2e:terminal-ibus-hangul-native
Defensive patterns

Strategy: validation

Validate before calling

const remaining = await stopOwnedProcessGroup(sessionProcess.pid)
if (remaining.length > 0) {
  console.error('X11 session survivors:', remaining)
}

Try / catch

const exitCode = await waitForExit(sessionProcess)
const remaining = await stopOwnedProcessGroup(sessionProcess.pid)
if (remaining.length > 0) throw new Error(`Owned X11 session processes survived cleanup: ${remaining.join('; ')}`)

Prevention

When it happens

Trigger: A process spawned inside the X11 session escaped the process group (setsid, reparented to init) or ignored the kill — e.g. Xvfb itself, a DBus daemon, or a re-activated ibus-daemon.

Common situations: xvfb-run's Xvfb child runs in its own session; DBus autostarts a session bus that escapes the group; a long-lived helper started with setsid; cgroup isolation blocks SIGKILL.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/5c6e4596e160c9ad. Report an issue: GitHub.

Appendix: source

Thrown at config/scripts/run-terminal-ibus-hangul-e2e.mjs:292

        IBUS_ENABLE_SYNC_MODE: '1',
        LANG: process.env.LANG || 'C.UTF-8',
        QT_IM_MODULE: 'ibus',
        XDG_CACHE_HOME: path.join(evidenceDir, 'cache'),
        XDG_CONFIG_HOME: path.join(evidenceDir, 'config'),
        XDG_RUNTIME_DIR: runtimeDir,
        XMODIFIERS: '@im=ibus'
      },
      stdio: 'inherit'
    }
  )
  if (!sessionProcess.pid) {
    throw new Error('xvfb-run did not return a PID')
  }
  console.error(`[terminal-ime] started isolated X11 session PID ${sessionProcess.pid}`)
  const exitCode = await waitForExit(sessionProcess)
  const remaining = await stopOwnedProcessGroup(sessionProcess.pid)
  if (remaining.length > 0) {
    throw new Error(`Owned X11 session processes survived cleanup: ${remaining.join('; ')}`)
  }
  return exitCode
}

const insideSession = process.argv[2] === insideSessionFlag
try {
  if (insideSession && !process.argv[3]) {
    throw new Error(`${insideSessionFlag} requires an evidence directory argument`)
  }
  process.exitCode = insideSession ? await runInsideSession(process.argv[3]) : await runOuter()
} catch (error) {
  console.error(`[terminal-ime] ${error instanceof Error ? error.message : String(error)}`)
  process.exitCode = 1
}

View on GitHub (pinned to 1136503c6a)