perf(macos): replace pgrep/lsof/ps with libproc for process introspection#146
Merged
Conversation
On macOS the close path, idle detection and port detection forked subprocesses to inspect processes: `pgrep -P` (child pids), `lsof` (dtach socket → pid, and listening ports) and `ps -eo pid,ppid` (process tree). Each fork+exec costs tens of ms on macOS (dyld + AMFI/codesign). Linux does the same via `/proc` reads; this brings macOS to parity with in-process `libproc` syscalls. New `okena_terminal::macos_proc` (macOS-only) wraps libproc: - `child_pids` / `has_children` / `first_child_pid` — `proc_listpids(PPID)`, replacing `pgrep -P`. - `process_name` — `proc_name`, gives the soft-close toast a foreground-command hint on macOS too (was Linux-only). - `process_tree` — `proc_pidinfo`/BSDInfo ppid, replacing `ps -eo pid,ppid`. - `pids_holding_unix_sockets` — scans each process's socket fds and matches the bound `sockaddr_un` path, replacing `lsof <socket>`. - `listening_port_pairs` — TCP sockets in LISTEN state → (pid, port), replacing `lsof -iTCP -sTCP:LISTEN`. Wired into `child_processes.rs`, `pty_manager.rs` (dtach lookup + first child) and `okena-services::port_detect`. libproc is a macOS-only dependency; Linux and Windows paths are unchanged, and other Unix (BSD) keeps the pgrep/lsof fallback. NOTE: the macOS code only compiles on macOS (libproc generates bindings via bindgen against the macOS SDK at build time). It is cfg'd out on Linux, so neither a Linux build nor the PR `check` job exercises it — it must be built on macOS (locally or via the tag/workflow_dispatch build matrix) before merge. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_019JZRfqVneyJnKjdrtSp3ro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
On macOS, several process-introspection paths forked subprocesses:
pgrep -Pproc_listpids(PPID)lsof <socket>(×2)lsof -iTCP -sTCP:LISTENps -eo pid,ppidproc_pidinfo/BSDInfoEach
fork+execon macOS costs tens of ms (dyld + AMFI/codesign). Linux already does all of this via/procreads; this brings macOS to parity with in-processlibprocsyscalls — no subprocesses.Companion to #145 (which moved the busy check off the GPUI thread). #145 fixes the perceived close lag regardless of backend; this removes the underlying
fork+execcost so the same introspection is cheap everywhere it's used (close path, idle detection, services panel).What
New macOS-only module
okena_terminal::macos_procwrappinglibproc:child_pids/has_children/first_child_pid— replacespgrep -Pprocess_name—proc_name; also gives the soft-close toast a foreground-command hint on macOS (was Linux-only)process_tree— replacesps -eo pid,ppidpids_holding_unix_sockets— matches boundsockaddr_unpaths; replaceslsof <socket>listening_port_pairs— TCPLISTENsockets →(pid, port); replaceslsof -iTCP -sTCP:LISTENWired into
child_processes.rs,pty_manager.rs(dtach lookup + dtach-daemon→shell walk) andokena-services::port_detect.libprocis a macOS-only dependency. Linux and Windows paths are untouched; other Unix (BSD) keeps thepgrep/lsoffallback (libproc is darwin-only).libprocgenerates its bindings via bindgen against the macOS SDK at build time, so the new module only compiles on macOS. It iscfg'd out on Linux, which means:checkjob (Linux-only clippy-D warnings+ tests) does not exercise it.It needs a macOS build before merge — either locally (
cargo build --target aarch64-apple-darwin) or via the multi-platformbuildworkflow (tag /workflow_dispatch). The code follows libproc's documented API, but the FFI/union/struct-field access is unverified by CI until then.Linux side (integration, cfg gating, BSD fallback) passes
cargo clippy --workspace --all-targets -- -D warnings.🤖 Generated with Claude Code