Skip to content

Session tracking & background processes#687

Merged
sylirre merged 3 commits into
masterfrom
feat/ps-session-tracking
Jun 21, 2026
Merged

Session tracking & background processes#687
sylirre merged 3 commits into
masterfrom
feat/ps-session-tracking

Conversation

@sylirre

@sylirre sylirre commented Jun 21, 2026

Copy link
Copy Markdown
Member

No description provided.

Track every active proot session so they can be enumerated, even when a
container has several running at once (login/run take a shared container
lock). Each session writes RUNTIME_DIR/sessions/<pid>.json and holds an
inherited exclusive flock on it: the fd's O_CLOEXEC is cleared so proot
keeps it across os.execvpe, and the kernel releases the lock when the
last holder exits. Liveness is therefore robust to crashes and kill -9
and never relies on os.kill(pid, 0), which PID recycling would fool.

The new `proot-distro ps` command lists active sessions as a
PID/CONTAINER/TYPE/USER/UPTIME/COMMAND table; `ps -q` prints PIDs only
for scripting. Listing probes liveness with a shared flock (so
concurrent `ps` runs don't misreport one another) and prunes dead
entries on sight.

Registration happens at the single os.execvpe chokepoint in
command_login (covers both login and run), after the --get-proot-cmd
early-exit, and is strictly best-effort so it can never block a session.

Wires the command into cli, parser, help pages, and the bash/zsh/fish
completions; documents it in README and CLAUDE.md. Adds unit tests for
the registry lifecycle, dead-entry pruning, concurrent listing, and ps
formatting/dispatch.
@sylirre
sylirre force-pushed the feat/ps-session-tracking branch from 7b699f2 to 73a8dbd Compare June 21, 2026 21:11
@sylirre sylirre changed the title Session tracking Session tracking & background processes Jun 21, 2026
@sylirre
sylirre force-pushed the feat/ps-session-tracking branch from a9eecba to d98fc95 Compare June 21, 2026 22:01
Background a container session as a daemon and return to the prompt
immediately. The detached session is listed by `proot-distro ps` and
stopped with `kill PID`.

Implementation:
- commands/login/detach.py: double-fork daemonization (setsid, std fds
  to /dev/null). register_session() runs in the grandchild so getpid()
  equals the future proot PID; a pipe relays that PID back to the
  foreground for the confirmation message.
- locking.py: ContainerLock.disown() closes the lock fd without LOCK_UN
  so the inherited fd keeps the shared container lock held by the daemon
  (flock releases on LOCK_UN of any duplicate, or once all close).
- session.py: record a `detach` flag in the session metadata.
- ps.py: mark detached rows as login*/run* with a legend.
- parser.py: -d/--detach on the shared login/run options.

Output is discarded to /dev/null; --get-proot-cmd still short-circuits
before the detach branch. Docs (README, CLAUDE, help pages) and
bash/zsh/fish completions updated.

Tests: test_locking.py (disown semantics), test_detach.py (real
fork+exec end-to-end via sleep), plus parser and session additions.
@sylirre
sylirre force-pushed the feat/ps-session-tracking branch from d98fc95 to 87d8c52 Compare June 21, 2026 22:06
`proot-distro ps` lists sessions by their proot PID and tells users to
stop one with `kill <PID>`, but that is unreliable: proot's
`--kill-on-exit` cleanup runs only on a graceful exit, so `kill -9` of
proot orphans the guest daemons (e.g. nextcloud's apache/php-fpm/cron),
and on non-Termux hosts `--kill-on-exit` is never set at all.

Add a `kill` command that signals the entire guest process tree. It
reads /proc to build a pid->ppid map, collects the transitive closure of
children under each target session's proot PID, and os.kill()s every
member (pure-Python — no pkill/pgrep/kill(1)).

- Targets: a PID, a container name (all its sessions), or --all. Always
  resolved against active_sessions(), so only tracked proot sessions can
  be hit, never an arbitrary host PID.
- Default signal SIGTERM; -s/--signal takes a name or number.
- PID-reuse safety belt: a root is walked only when /proc/<root>/comm
  reads "proot". Never signals self, pid 0, or pid 1.
- Exempt from the startup proot probe (it only signals running sessions).

Wired into parser, cli dispatch, help pages, bash/zsh/fish completions,
README, and CLAUDE.md. Adds unit tests for the pure tree walk and signal
parsing plus a live-process teardown integration test.
@sylirre
sylirre force-pushed the feat/ps-session-tracking branch from c546cf7 to 8ac3106 Compare June 21, 2026 23:09
@sylirre
sylirre merged commit caf084b into master Jun 21, 2026
6 checks passed
@sylirre
sylirre deleted the feat/ps-session-tracking branch June 21, 2026 23:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant