Skip to content

Preview canary stalls after Ready to restart: quitAndInstall never completes the install #441

Description

@vishaltandale00

Problem

The Apple Silicon Preview canary for 0.2.29 to 0.2.30 (run 33679270867) reached "Ready to restart" and then never relaunched into the target. It sat for ~43 minutes and was cancelled.

This blocks Stable promotion, because promotion requires committed canary evidence and the run produced no post-update screenshot and no evidence JSON.

Evidence

Everything up to the install succeeded:

Step Result
0.2.29 installs from DMG, launches pass
Discovers 0.2.30 on Preview pass
Downloads to pending cache pass
Reports ready, screenshot captured pass
updater.install() invoked pass
App quits never happened
Squirrel installs and relaunches never happened

seed-update.log ends at:

New version 0.2.30 has been downloaded to .../pending/Relayer-0.2.30-mac-arm64.zip
Creating proxy server for native Squirrel.Mac (fileToProxy=...)
Proxy server for native Squirrel.Mac is listening (address=http://127.0.0.1:49233, ...)

then silence. At job cleanup the runner terminated Relayer, relayer-graph-server, relayer-app-server and two Relayer Helper processes as orphans, so the app was alive and holding its children throughout.

Ruled out

  • The Desktop 0.2.29 cannot start on any existing database: search rebuild over-counts edges for project-scoped closures #435 startup bug. The preview-ready screenshot shows the seed at provider onboarding with no thread and no graph content, so the profile had no edges.
  • The managed-runtime quit dialog. confirmManagedRuntimeQuit returns true immediately when installer.activeOperations() is empty, which matches onboarding.
  • Graph runtime shutdown. #closeResources and #closeHarnessHost are deadline-bounded with force-close fallbacks.
  • The recursive temporal chain. Launching packaged 0.2.30 locally with an isolated profile and the chain enabled, then signalling quit, exits in 1 second with all children gone.

Hypothesis

The failure is specific to the quitAndInstall path, which the local quit test does not exercise.

updater.install() calls autoUpdater.quitAndInstall(false, true), which internally requests an app quit. The before-quit handler then calls event.preventDefault() and runs an async shutdown before calling app.quit() itself:

app.on("before-quit", (event) => {
  if (shutdownComplete) return;
  event.preventDefault();
  ...
  await shutdownServices();
  shutdownComplete = true;
  app.quit();
});

Cancelling the quit that quitAndInstall initiated, then quitting separately later, is a fragile coordination with electron-updater's Squirrel handoff. Worth verifying whether the install survives a deferred quit, or whether the updater needs to be told to install after shutdown settles rather than racing it.

Also note shutdownServices() awaits productServer.close(), accountService.close() and providerComposition?.close() with no deadline at that seam; only graphRuntime.close() is bounded. That is a separate latent stall risk even though it was not implicated here.

Why it matters beyond CI

If the packaged updater can reach "Ready to restart" and then fail to install, users clicking Restart to update may silently stay on their current version. That is especially bad for anyone on 0.2.29, which cannot start once their graph contains edges (#435).

Acceptance

  • The Apple Silicon canary completes a full seed-to-target update and emits post-update evidence
  • quitAndInstall reliably installs when the app performs asynchronous shutdown first
  • Shutdown closes that can stall are bounded, or explicitly documented as unbounded by design

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions