Skip to content

Keep automatic updates going after slow downloads, retry refused updater starts, skip updates during sign-out - #198

Merged
Views2k merged 3 commits into
mainfrom
fix/update-274-failures
Nov 9, 2026
Merged

Views2k merged 3 commits into
mainfrom
fix/update-274-failures

Conversation

@Views2k

@Views2k Views2k commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner

Fixes the Wisp defects behind the failed 2.7.3 → 2.7.4 updates on 2026-11-08. 4 of 61 installs that tried the update had a failure (6.6 %). Two were defects (3.3 %): one Steam install whose automatic updates stopped for the session, and one Xbox install whose updater starts Windows refused. The third failure, during a Windows sign-out, is handled too. The fourth was a one-off timeout that recovered on its retry.

Closes #191
Closes #190
Closes #192

Changes

Slow downloads no longer end automatic updates (#191)

  • A download that times out or loses its connection before GitHub answers doesn't count toward the three-attempt limit. It is retried after 2 min, then every 15 min. Its failure is reported once per reason until a download succeeds, as for update checks.

  • Verification, storage and helper failures still count toward the limit, and so does an HTTP error status.

  • The installer download's requests, redirects included, wait up to 60 s for a response. Update checks keep 15 s.

  • A check or download that reaches its response deadline reports update.download with its incident, with:

    • request: which request of the chain timed out (release-page, release-api, installer, installer-redirect-N);
    • connectMs: name resolution and TCP connect of a connection that request opened;
    • tlsMs: that connection's TLS handshake, including the online certificate revocation check;
    • responseMs: the wait for the response.

    The last phase present is the one the deadline interrupted. A helper failure's evidence keeps its recovery, which this evidence leaves out; the measurements stay out of the signature.

  • To time the phases, the update transport is now a SocketsHttpHandler:

    • its ConnectCallback makes the default connection;
    • its PlaintextStreamFilter passes the stream through unchanged and marks the end of the TLS handshake.

    All other settings are unchanged: no redirects, no decompression, no cookies, no credentials, no proxy, online revocation check, no certificate callback, 16 KB header limit, one connection per server. The transport test asserts them.

  • Ordering: Wisp Tools must accept update.download before any build with this change reports to it. Its incident validation rejects unknown fields, and the whole incident would get a 400. Views2k/wisp-site#441 adds that support and must be live before this PR is marked ready or a test installer is built.

Refused updater starts are retried; a staged installer is reused (#190)

  • ProcessStartRetry, in Wisp.Update, tries a start again after 1, 2, 4 and 8 s (15 s in all) when Windows answers access denied (5) or a sharing violation (32). Any other error fails at once.
  • Wisp uses it to start the helper (ApplicationUpdateLauncher). The wait doesn't block the dashboard thread. Before each retry it checks that the update may still start (not paused, not exiting, not signing out).
  • The helper uses it to start the installer (UpdaterProcessHost) and checks for Forza before every start.
  • After the helper restarts Wisp, Wisp checks an installer that an earlier attempt staged for the release (file name, size, SHA-256, PE identity and version) and installs it instead of downloading it again. The helper verifies it again before it runs, as before.

No update during sign-out or shutdown (#192)

  • The session-end sentinel now also marks Windows as signing out or shutting down, and clears the mark when Windows withdraws the notice. While it is set, CanBeginApplicationUpdate and the automatic coordinator start nothing, and an ongoing hand-off stops at its next guard.
  • A helper exit with 0xC000026B (window station shutting down) is recorded as a cancelled hand-off, not an update failure.

Verification

  • On Linux (.NET SDK 10.0.402), with Windows targeting:
    • Wisp.Update, Wisp.Updater, Wisp.App and the test projects compile with no warnings. dotnet format --verify-no-changes passes on every changed file.
    • Wisp.Update.Tests: 132 pass, including the new deadline, request-timing, loopback connection-timing and start-retry tests. The 17 that need the Windows test fixture .exe, the new staged-installer tests among them, run in Windows CI.
    • Wisp.Updater.Tests UpdaterWorkflowTests: 8 of 10 pass. The installer-retry test and an existing timeout test need ComSpec and run in Windows CI.
  • Wisp.App.Tests (coordinator back-off, helper start retry, session-end exit, staged-installer lookup) compile but need Windows; CI runs them.
  • Steam and Xbox: the update path has no platform-specific code, and each change applies to both alike. By platform, the failures were:
    • Steam: the session-long stop after three timeouts, plus the one-off that recovered.
    • Xbox: the refused starts, and the start during sign-out.
    • Neither platform was tested on a real PC; see below.

Not verified

  • What made GitHub's responses slow on the Steam installs (update checks of about 12 s, against 0.3–1 s elsewhere). The new timings will show whether the TCP connection, the TLS handshake (with its revocation check) or GitHub's response is the slow step, once a build with this change runs on such a PC.
  • What denied the helper and installer starts on the Xbox install. Wisp's staging keeps default permissions, and the installer lease allows execution; nothing in the telemetry identifies the source. The retry limits the effect.
  • Whether Windows' sign-out notice reached Wisp before Forza closed on the install whose helper exited with 0xC000026B. That PC hasn't run Wisp since, so its exit record hasn't arrived.
  • No gameplay or installer run on Windows; this needs a test installer on a Steam and an Xbox PC.

…ter starts, and skip updates during sign-out

- A download that times out or loses its connection before GitHub answers no
  longer spends the release's three-attempt budget. It is retried after 2 min,
  then every 15 min, and its failure is reported once until a download succeeds.
  Verification, storage and helper failures keep the budget.
- Installer download requests wait up to 60 s for a response; update checks
  keep 15 s. A response timeout now records which request of the chain timed
  out, whether it opened a connection, and how long the TCP connection took.
- Starting the update helper or the installer is tried again after 1, 2, 4 and
  8 s when Windows answers access denied or a sharing violation. The helper
  re-checks for Forza before each start.
- After the helper restarts Wisp, an installer already staged for the release
  is verified again (name, size, SHA-256, installer identity) and installed
  instead of being downloaded again.
- No update hand-off starts between Windows' sign-out or shutdown notice and
  its withdrawal. A helper that exits with 0xC000026B (window station shutting
  down) is recorded as cancelled, not as an update failure.
An update check or download that reaches its response deadline now reports
update.download with the incident: which request of the chain timed out, and
how long its TCP connect, TLS handshake and response wait took. The handshake
is timed with the transport's plaintext stream filter, which passes the stream
through unchanged. The measurements stay out of the incident signature.
@Views2k
Views2k marked this pull request as ready for review November 8, 2026 21:37
@Views2k
Views2k merged commit 6acfec5 into main Nov 9, 2026
10 checks passed
@Views2k
Views2k deleted the fix/update-274-failures branch November 9, 2026 03:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant