bee97055dbe9fc69b8e390d79329795cb3aa7938
2 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
1cd4f18e92 |
feat: spawn the Rust companion binaries, not Python scripts
The launcher shelled out to `python3 lsx_responder_v2.py` and `python3 autopatch.py` from a configured tools directory. Both are now Rust binaries built from this workspace (openfut-lsx, openfut-autopatch), so the launch contract loses the interpreter and the script directory entirely: nothing to locate, nothing to configure, and no way to run a stale checkout's copy of a responder. Service::script() becomes Service::binary(), and resolve_binary() prefers a sibling of the running launcher -- what a workspace build and any sane install layout both produce -- falling back to the bare name so a PATH install still works. It returns the bare name rather than failing so that spawn() stays the single place a missing binary is reported, instead of two error paths for one condition. foreign_pid() now matches an argv entry's FILE NAME rather than a suffix, so `/path/to/openfut-lsx` matches while an unrelated argument that merely ends with the same text does not. It deliberately still reads argv and not comm: comm is truncated to 15 characters by the kernel, which would misreport both of these names -- the same trap that made an earlier `pgrep -f` guard match its own shell. Dead configuration removed rather than left vestigial: fifa17_python and fifa17_tools_dir, their Settings controls, and validate_local_services(), whose only two checks were those fields. A validation hook that can only return Ok(()) would claim the launcher verifies local-service configuration when there is none. The preflight tools-dir gate is gone too, while the ptrace_scope check it gated is kept -- that check is real and repairable via "Arm client"; only the gate died. The env contract is unchanged, so the binaries are drop-in: LSX still receives FUT_PERSONA_ID/FUT_PERSONA_NAME (the persona has to agree with Blaze's LoginResponse.SESS.PDTL and UTAS's userInfo.personaId), autopatch still receives OPENFUT_AUTOPATCH_LOG under XDG_RUNTIME_DIR and --launcher-pid so it cannot outlive its owner, and each companion still gets its own process group. 74 tests green. |
||
|
|
3174fe4c1f |
launcher: one Launch button, driven by an explicit launch state machine
The launcher used to make the user perform OpenFUT's internal launch order by
hand — Start LSX, Start autopatch, Run pre-launch checks, "Arm client", then a
button called *Start Services & Launch Game*. Those are implementation details
of how FIFA 17 is persuaded to talk to OpenFUT, and getting the order wrong
produced failures that surfaced much later as "the game crashed": autopatch
started before ptrace_scope is 0 silently patches nothing at all.
The normal flow is now: open the launcher, read one status card, press
**Launch FIFA 17**.
New `launch` module holds the sequence as a state machine (Phase: Idle,
Checking, PreparingClient, StartingServices, Validating, Launching, Running,
Failed) and runs it on a worker thread, so the UI thread never blocks on a
socket, a Polkit prompt or a process spawn. The UI renders that state; it does
not coordinate services.
Every step asks what is already true before acting:
- a healthy service is reused, never restarted;
- client preparation is skipped when the checks it would repair already pass,
which also avoids a pointless password prompt;
- the hook config is reconciled from the current settings.
It stops at the first failed step and never starts FIFA into a client it knows
is broken. Preparation deliberately runs BEFORE autopatch, against the order in
the brief, because autopatch cannot write FIFA's memory until arming has set
ptrace_scope and would otherwise "succeed" while doing nothing.
Ownership is now tracked, which the old model could not express: it only knew
about children it had spawned, so a service started by hand for a debugging
session read as "stopped" and starting it again just collided on the port.
`ServiceSupervisor` observes our own child first, then scans /proc for a foreign
instance, and reports `ServiceRuntime { running, started_by_launcher, pid,
detail }`. `stop_permitted` refuses to kill anything the launcher did not start,
under any cleanup policy. `CleanupPolicy` states the shipped behaviour — leave
launcher-started services running for the next launch — instead of leaving it to
chance, and the FIFA-exit path goes through it.
Readiness comes from observation, never from a button press: LSX is ready only
when the port FIFA dials is actually held, and "we have not looked" renders as
"Not checked yet", never as green.
Manual controls all survive under **Advanced / Diagnostics** — per-service
start/stop/restart with PIDs and ownership, "Prepare client" (the old "Arm
client", renamed; internals still say arm), "Run pre-launch checks", "View
logs", and a new "Launch game only" escape hatch for debugging a launch the
sequence refuses.
Tests: 73 pass (15 new). Sequencing and ownership are unit-tested through a
`LaunchOps` fake, so "don't launch after a failed step", "don't restart healthy
services" and "don't kill what we didn't start" hold without a FIFA install, a
Polkit agent or root.
Exercised live under Xvfb: the card shows four observed rows and one button; a
launch stopped at LSX with "127.0.0.1:4216 is held by an unrelated process",
listed every step's verdict, and did NOT start the game; Advanced showed a real
pre-existing autopatch as "Running (foreign) · pid 382382 · started outside this
launcher" with Stop/Restart disabled.
|