together: scope seat-streamers into the launch slice #5

Merged
gabrielgad merged 1 commit from fix/together-seat-streamer-lifecycle into main 2026-06-17 08:35:49 -04:00
gabrielgad commented 2026-06-17 08:35:43 -04:00 (Migrated from github.com)

Problem

Seat-streamers were spawned as bare children, inheriting splitux-main-*.scope instead of the per-launch splitux-<id>.slice. On a hard kill/crash of splitux — or a manual systemctl --user stop splitux.slice — they orphaned and kept their virtual input devices alive. The next launch's gamescope then grabbed the stale event nodes via --libinput-hold-dev, so input never reached the game (the "input not passed to the game" failure seen during local-split testing).

Fix

Spawn each seat-streamer inside the launch slice via a new scope::wrap_seat_command (a -seat{idx} scope, sibling to instance -i{idx} scopes). It now:

  • BindsTo the main scope → dies with splitux on any signal (hard kill, crash, normal exit),
  • is reaped by the launch-slice teardown and the startup sweep,
  • has its uinput devices auto-removed on exit.

Also hoisted the scope/launch-id setup above seat-streamer spawn so launch_id/main_scope are available, and refactored wrap_command to share a wrap_in_scope core (stdio intentionally not copied — applied after wrapping in spawn_seat_streamer).

Verified

  • Seats land in splitux.slice/<id>.slice/<id>-seatN.scope.
  • systemctl --user stop splitux.slice now reaps seat-streamers + gamescope + game + virtual devices + overlays → all 0 (previously left orphan seat-streamers + devices).
  • Moving Out local-split launches + streams fine on the rebuilt binary.
## Problem Seat-streamers were spawned as bare children, inheriting `splitux-main-*.scope` instead of the per-launch `splitux-<id>.slice`. On a hard kill/crash of splitux — or a manual `systemctl --user stop splitux.slice` — they orphaned and kept their virtual input devices alive. The next launch's gamescope then grabbed the **stale** event nodes via `--libinput-hold-dev`, so input never reached the game (the "input not passed to the game" failure seen during local-split testing). ## Fix Spawn each seat-streamer **inside the launch slice** via a new `scope::wrap_seat_command` (a `-seat{idx}` scope, sibling to instance `-i{idx}` scopes). It now: - `BindsTo` the main scope → dies with splitux on any signal (hard kill, crash, normal exit), - is reaped by the launch-slice teardown and the startup sweep, - has its uinput devices auto-removed on exit. Also hoisted the scope/launch-id setup above seat-streamer spawn so `launch_id`/`main_scope` are available, and refactored `wrap_command` to share a `wrap_in_scope` core (stdio intentionally not copied — applied after wrapping in `spawn_seat_streamer`). ## Verified - Seats land in `splitux.slice/<id>.slice/<id>-seatN.scope`. - `systemctl --user stop splitux.slice` now reaps seat-streamers + gamescope + game + virtual devices + overlays → all 0 (previously left orphan seat-streamers + devices). - Moving Out local-split launches + streams fine on the rebuilt binary.
Sign in to join this conversation.
No description provided.