Session-restored windows start outside bypass #113
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Split out of #67 (PR #112). KDE session restore relaunches apps from the command line recorded at session save, not by resolving desktop entries — so a listed app restored at login starts outside the bypass cgroup, and stays out until manually restarted through any covered path.
This is inherent to deterministic launch-time placement: session restore passes through no launcher, so there is nothing to shim. Related same-family gap, already documented in the README: kglobalaccel captures each shortcut's KService at registration (verified against kglobalacceld's
KServiceActionComponent, which stores theKService::Ptrat construction), so global-shortcut launches pick up list changes only at the next login.Candidate directions, none pretty:
app-<id>@autostart.service, session-restore scopes), so their pids are discoverable without process-name guessing and could be migrated into the cgroup when it appears. This is migration-after-the-fact rather than launch-time placement, but driven by unit names, not a process watcher — worth weighing against the doctrine if the gap turns out to matter in practice.Recording the full watcher assessment from the PR #112 discussion, since this issue is where sweep-vs-watcher gets decided. To be precise about history first: process watching was never banned on principle — ProtonVPN's implementation was found unstable (dropped fork events from lossy perf buffers), and that instability is this fork's origin story. The question worth answering is whether a careful watcher would be sound. It wouldn't, for three separate reasons:
1. The Proton failure is mitigable — this part is fixable. Perf buffers drop silently, but the newer BPF ring buffer and the netlink proc connector both make drops detectable (failed reserve / ENOBUFS), so an implementation can rescan /proc on drop and become eventually consistent. Cost: eBPF toolchain, extra capabilities, and kernel-version sensitivity inside a root service that is currently plain Python.
2. The socket-tagging race is not mitigable. cgroup v2 associates a socket with its creator's cgroup at socket creation; migrating the process later does not retag existing sockets. A watcher classifies after exec by definition, so any connection opened before the migration stays classified the old way for its whole life — and long-lived connections opened at startup are exactly what chat clients, torrent clients and launchers do first. Launch-time placement (join-then-exec) is immune by construction: the app never runs an instruction outside the cgroup, so every socket it ever opens is tagged right. This is the structural reason, independent of any implementation quality.
3. Classification is guesswork at runtime. A watcher sees a pid and a binary path and must decide "is this a listed app?" — the same fuzzy Exec-to-entry matching rejected elsewhere, but system-wide, continuous, and consequential in both directions.
Conclusion: a fixed watcher buys a bigger promise it structurally can't keep ("most traffic, after the first milliseconds, usually"), versus the current smaller promise kept 100% of the time. For the residual gaps this issue tracks, the unit-name sweep at bypass activation recovers most of the value with none of the watching — with the honest caveat that it shares the pre-existing-socket limitation from point 2, which is why launch-time coverage stays primary and the sweep could only ever be a safety net.
Decision: this lands in 0.9.1, not later — if bypass is a headline feature of the release, the feature should be as good as reasonable, so the known hole gets closed in the same release. Ships as its own PR after #112 merges (one mechanism per PR).
Settled direction, per the analysis above: a deterministic sweep, no watching.
Correcting my earlier comment on this issue: I wrote that the sweep would also catch "launches through KDE's per-session shortcut cache". That is only true for launches that precede the next activation. The sweep runs at bypass activation and deliberately not continuously, so a shortcut launch during an already-active session is caught by nothing until bypass re-activates.
The real fix for that path is re-login — kglobalaccel then resolves the .desktop override and the launch is placed at exec time, which is the guarantee that actually holds (see socket tagging: migration after the fact never retags existing sockets). Verified live on a session where Ctrl+Alt+T kept launching unwrapped konsole while menu launches were correctly bypassed.
Scope as implemented: the sweep covers apps already running when bypass activates — session restore, and autostart entries that beat activation despite --wait. Nothing else.