add: sweep already-running listed apps into bypass at activation (#113) #114
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/bypass-unit-sweep"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #113. Follows #112 (launch-time placement); this is the safety net behind it, per the plan settled on the issue.
Problem: launch-time placement only catches launches that pass through a launcher. A listed app restored by session restore, or started before the GUI at login, keeps running on the tunnel with nothing to correct it.
Fix: a deterministic sweep at bypass activation — no process watching.
bypass.sweep_units(desktop_ids, uid)walks the user manager's cgroup tree, recovers the desktop id systemd embeds in each app unit's directory name (app-<id>@<instance>.service,app-<id>.service,app-<id>-<pid>.scope), and moves the pids of matching units — nested unit cgroups included — into the bypass cgroup. Names are parsed before unescaping, so a\x2dinside an id can't be mistaken for the literal dash before a scope's pid.Reach beyond session restore: also backstops the two paths #112 left open — autostart entries that beat activation despite
--wait, and launches through KDE's per-session shortcut cache (kglobalaccel's staleKService), since both land in normal app units.Carried limitation: sockets opened before the move keep their old classification — cgroup v2 tags a socket at creation and migration doesn't retag it. So the sweep is a safety net, not a substitute for launch-time placement. The README now says this where a user meets it: restart the app if it matters that all of its traffic bypasses.
Verification: 255 tests pass (13 new: unit-id parsing across service/scope/autostart/escaped-dash/foreign-dir forms, sweep matching, nested cgroups, unlisted units, prefix collisions, missing cgroup). ruff + compileall clean. The parser was also validated read-only against this machine's live cgroup tree — all 14 real app units parse correctly, including
app-arch\x2dupdate\x2dtray@autostart.serviceand both scope forms.Live round: with a listed app already running, connect with bypass enabled → journal should log "moved N already-running process(es) into the cgroup", and a new connection from that app (fresh tab/request) should show the bypass IP while its pre-existing connections stay on the tunnel.
🤖 Generated with Claude Code
Reworked after review: the sweep was in the wrong process.
Activation is the service's event — it builds the cgroup — and
aqomui-cliactivates bypass too (aqomui_cli.py:211, :382), so with the sweep in the GUI, cli-driven activation and any service restart without a running GUI swept nothing. That left the gap open on precisely the paths where no GUI mediates — self-defeating for an issue whose motivation is "launches the GUI never saw".bypass()now sweeps after building the cgroup, reading the owner's app list from their home via the uid it already derives from the kernel sender (#89, same derivationimport_threaduses for its download dir).Two things that changed with it:
load_bypass_listdrops non-objects and malformed entries instead of carrying them further, and desktop ids are basenames — nothing in the list can express a path.sweep_unitschecks pid ownership explicitly. Unprivileged callers got that from the kernel for free (writingcgroup.procsrequires owning the process); as root nothing enforces it, so the guardreclaim_straysalready carries is now here too.The GUI keeps exactly one sweep — adding an app while bypass is already up, which produces no service call to hang one on — and its id math moved to
launcher.sweep_running, besiderefresh_autostart: same input, same domain, and a module the cli imports anyway (#83).265 tests pass (10 more: untrusted-list handling, basename-only ids, ownership filtering, sweep_running plumbing).
0daa0af15b13897d68e2Two corrections to earlier claims in this PR, plus the sweep consolidation.
Correction — the sweep does not catch KDE global-shortcut launches. I claimed it did, in the PR body and on #113. It only holds when the launch precedes the next activation: the sweep runs at activation, deliberately not continuously, so a Ctrl+Alt+T launch during an already-active bypass session is caught by nothing until something re-activates bypass. What actually fixes shortcut launches is re-login, after which kglobalaccel resolves the override and placement happens at launch time. Confirmed live.
The gui no longer sweeps. There were two
sweep_bypass_unitsmethods, in two files, logging the same sentence — and since the service's log is forwarded into the gui's log pane, that line could appear there from either process with nothing distinguishing them. That ambiguity lands squarely in the artifact used to debug bypass.Resolved by deletion rather than by adding a
sweep_bypass()method: the service owns the cgroup, so nothing else writes tocgroup.procs. The gui's sweep was the one worth losing — sweeping on a list edit buys little, because a running app keeps the connections it already opened either way (cgroup v2 tags a socket at creation), which is exactly what the notification already tells the user to fix by restarting. Activation stays swept: a dozen listed apps can be running at login, and "restart them all" is no answer.Folding it into
bypass()was considered and rejected —create_cgroupopens withdelete_cgroup, sobypass()is a full teardown/rebuild plus a dnsmasq restart, far too much for ticking a box.274 tests green.
af49c5253ee971dd10f8