Skip to content

fix(install): Stream (beta) crashed the helper — skip in-process install#184

Merged
phantomptr merged 2 commits into
mainfrom
fix/stream-install-serve-only
Jul 6, 2026
Merged

fix(install): Stream (beta) crashed the helper — skip in-process install#184
phantomptr merged 2 commits into
mainfrom
fix/stream-install-serve-only

Conversation

@phantomptr

Copy link
Copy Markdown
Owner

Description

Fixes a 3.3.25 regression: streaming-installing a .pkg ("Stream (beta)") crashed the PS5-side helper — the console "stopped responding" and went unreachable.

Root cause (from the bug bundle's engine.log)

pkg_install: url=http://…/pkg-host/…UP1082-CUSA03474…pkg  →
pkg_install RPC failed: read frame header  (30002ms)

The stream path went through the normal in-process installer with an http:// pkg-host URL. On FW < 11 that InstallByPackage call triggers Sony's PlayGo HTTP preflight and hangs the payload's RPC thread for 30 s until its watchdog kills the helper. The DPI daemon — which is supposed to do the streaming install in a separate loader process — never got a turn, because the "register the serving session" step already crashed the console. dpi-direct-install was never reached (count 0 in the log).

It's a client↔engine contract mismatch: installStream's step-2 comment says pkg_install_start "creates a pkg-host serving session WITHOUT expecting a staged file," but install_start_handler had no such mode — it always sent the in-process install frame.

Fix

Add serve_only to InstallStartRequest (default false — the normal/staged install path is completely untouched). When true, install_start_handler builds + registers the /pkg-host/ session (which already carries the PC file path in parts, so serve_handler streams it) and returns the session_id without the in-process install. installStream now passes serve_only: true; its step 3 (runDpiDirectInstalldpi_ensurepkg_dpi_direct_install) does the real install via the DPI daemon pulling over HTTP — exactly as designed.

Testing

  • Engine + desktop + client build clean; engine 80 tests (2 new pinning the serve_only serde default + parse, so the crashing path can't silently return); client lint + pkgLibrary tests green.
  • ⚠️ Not yet hardware-verified. The reporter's Pro is currently wedged from the original crash (helper accepts TCP but won't answer RPCs); reloading the payload needs a physical jailbreak re-run. The fix removes the exact call that hung the helper — re-test on the Pro after a payload reload.

Type of Change

  • Bug fix (crash regression in a shipped beta feature)

🤖 Generated with Claude Code

phantomptr and others added 2 commits July 6, 2026 04:08
Reported against 3.3.25: streaming-installing a .pkg on FW 9.60 made the PS5
"stop responding" (helper dead, console unreachable). Root-caused from the
bug bundle's engine.log:

  pkg_install: url=http://…/pkg-host/…  → RPC failed: read frame header (30002ms)

The stream path went through the NORMAL in-process installer with an http://
pkg-host URL. On FW < 11 that InstallByPackage call triggers Sony's PlayGo
HTTP preflight and HANGS the payload's RPC thread for 30s until the watchdog
kills the helper. The DPI daemon — the thing that's SUPPOSED to do the
streaming install in a separate loader process — never got a turn, because
the "register the serving session" step already crashed the console.

The bug is a client↔engine contract mismatch: installStream's step-2 comment
says pkg_install_start "creates a pkg-host serving session WITHOUT expecting a
staged file," but install_start_handler had no such mode — it ALWAYS sent the
in-process install frame.

Fix: add `serve_only` to InstallStartRequest (default false, so the normal/
staged path is untouched). When true, install_start_handler builds + registers
the /pkg-host/ session (which already carries the PC file path in
`parts`, so serve_handler can stream it) and returns the session_id WITHOUT
the in-process install. installStream now passes serve_only:true; its step 3
(runDpiDirectInstall → dpi_ensure → pkg_dpi_direct_install) does the real
install via the DPI daemon pulling over HTTP — exactly as intended.

Engine + desktop + client build clean; engine 80 tests (2 new pinning the
serve_only serde default + parse); client lint + pkgLibrary tests green.

NOT yet hardware-verified: the reporter's Pro is currently wedged from the
original crash (helper accepts TCP but won't answer RPCs) and reloading the
payload needs a physical jailbreak re-run. The fix removes the exact call that
hung the helper, so re-test on the Pro after a payload reload.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The serve_only param pushed pkg_install_start to 8 args, tripping
clippy::too_many_arguments (8/7) under -D warnings — the rust-desktop CI
failure on #184. cargo build (my local check) doesn't run clippy, so it
passed locally; should have run clippy. Tauri commands mirror their JS
invoke call site, so the arg count is dictated by the API surface, not Rust
ergonomics — the standard exception. Scoped #[allow] with that rationale.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@phantomptr phantomptr merged commit 1961772 into main Jul 6, 2026
23 checks passed
@phantomptr phantomptr deleted the fix/stream-install-serve-only branch July 6, 2026 11:22
phantomptr added a commit that referenced this pull request Jul 6, 2026
…y it (#185)

Follow-up to the stream-install crash fix (#184), from the FW assessment.
Two gaps that made "stream install is great" false, especially on FW 12:

1. FW-11 guard (client). The Stream path installs via the standalone DPI
   daemon, which has no kernel R/W and so can't acquire the SYSTEM install
   authid that FW 11+ requires for the content-copy — on FW 11+ it registers
   the title but lands NO content ("hollow" tile). The in-process installer
   (normal Upload→Install) DOES escalate correctly. So before a stream install
   on a console we KNOW is FW 11+, warn and point the user at the normal path
   (they can still proceed). Below FW 11 / unknown FW is unaffected. New
   `firmwareMajor()` helper (+3 tests) off the existing kernel-string parser.

2. Verify actually verifies (engine). install_status_handler returned CONFLICT
   for a session with no BGFT task_id — which is EVERY stream (serve_only)
   session — so the client's verifyInstallCompleted fell through to its
   optimistic "can't verify → assume done" branch and reported success without
   checking. A stream session has no task_id (the DPI daemon did the install in
   its own process), but completion is verifiable the SAME way the normal path
   verifies a Done: the on-disk launch-check (verify_launchable → is
   /user/app/<id>/app.pkg present) + byte observation, both filesystem-based
   and task_id-free. Synthesize a Done phase for the no-task_id case so the
   existing adaptive tracker runs (Registered ⇒ complete, Absent ⇒ still
   installing, flatline ⇒ stall). This also catches a hollow tile if a FW-11+
   user proceeds past the guard.

Engine build+fmt+clippy+80 tests, desktop clippy, client typecheck+lint+782
tests (+3), i18n 18 langs — all green. Still pending HW verification on the
Pro (FW 9.60) once its payload is reloaded.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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