Closed bug report

Self-update relaunch races itself and runs `wsl --shutdown`, terminating every WSL distro on the machine including the user's own

kaleymer · 1mo ago ·closed by John Lauer

Updating Hydrogen 1.0.424 → 1.0.431 killed an unrelated personal WSL distro (Ubuntu-24.04), dropping a live VS Code Remote-WSL session. Hydrogen recovered only Adom-Workspace; the personal distro stayed stopped, with no indication anything had happened to it.

Timeline

From %APPDATA%\hydrogen-desktop\hydrogen-desktop.log, 2026-09-17:

13:36:50  === Hydrogen Desktop started ===  BUILD_STAMP=d20faa13… (1.0.424)
13:36:50  [single-instance] second HD launch detected — focused hd
13:37:15  updater_install invoked (banner/UI)
13:37:15  Update available: 1.0.424 -> 1.0.431
13:37:17  Spawned relauncher (waits for installer pid=15120); exiting so the installer can replace files
13:37:21  === Hydrogen Desktop started ===  BUILD_STAMP=efa29719… (1.0.431)
13:37:24  === Hydrogen Desktop started ===  BUILD_STAMP=efa29719… (again, 3s later)
13:37:25.648 [ports] default 47083 for proxy still unusable: Only one usage of each socket address … (os error 10048)
13:37:25.649 [ports] default 47084 for control still unusable: … (os error 10048)
13:37:25.650 [ports] default 47085 for cdp still unusable: … (os error 10048)
13:37:25.673 [app] previous run ended UNCLEAN (no clean-shutdown marker)
13:37:25.737 [runtime-kv] published hydrogen.runtime.k_zephyrus (instance=hd-19452-…)
13:37:25.818 [wsl] service looks WEDGED (E_UNEXPECTED), self-healing: wsl --shutdown, settle, retry once
13:37:25.818 [cmd] $ wsl --shutdown
13:37:28.839 [wsl] --shutdown ok, waiting for the service to settle
13:37:44.098 [wsl] RECOVERED after --shutdown: ["-d","Adom-Workspace",…] succeeded on retry

Two defects, one compounding the other

1. The update relaunch produces overlapping instances. Three starts in 34 seconds, and the three os error 10048 ("address already in use") lines prove the 13:37:21 instance still held 47083/47084/47085 when the 13:37:24 instance came up. Two copies of Hydrogen were alive simultaneously, both talking to wslservice.

2. A single generic COM error triggers a machine-wide destructive command. The 13:37:24 instance fired wsl --shutdown 81 ms after publishing its runtime key, on one E_UNEXPECTED — which is exactly what concurrent callers racing a busy wslservice produce. wsl --shutdown is not scoped to a distro: it terminates the entire WSL utility VM and every distro in it, including docker-desktop and any personal distro Hydrogen never created.

Hydrogen already has the right behavior elsewhere

The WSL_WEDGED path is careful:

[wsl] WSL_WEDGED declared: 3 consecutive wsl.exe timeouts (last: workspace_stats probe (3s)).
      The Windows WSL management plane (wslservice) is not responding; the distro itself may be
      fine. Suppressing non-essential wsl.exe calls; workspace health falls back to HTTP probes.

Three consecutive timeouts before declaring, an explicit statement that the distro is probably fine, and a response that backs off instead of shutting anything down. That path handled two real wedges on 2026-09-14 (13:33 and 17:29, both immediately following sleep/resume) and cleared on its own within 9 seconds each time, with no collateral damage. The two code paths react to the same underlying condition — wslservice not answering — with opposite levels of aggression.

Impact

Silent termination of distros belonging to the user rather than to Hydrogen. Running processes, /tmp contents, and unsaved editor state in those distros are lost. In this case a VS Code Remote-WSL session into Ubuntu-24.04 was severed; VS Code then served a cached endpoint and reported Cannot register remote filesystem provider. Error while fetching remote environment. WebSocket close with status code 1006 on every reconnect and every newly opened window, which is not an obvious pointer back to Hydrogen.

The README currently promises the opposite:

stays cleanly separated from the rest of your system, including your other WSL distros and Docker Desktop, which Hydrogen never touches

Suggested fixes

  1. Never call bare wsl --shutdown. wsl --terminate Adom-Workspace is the same remedy for Hydrogen's own distro with no blast radius.
  2. Route the E_UNEXPECTED case into the existing WSL_WEDGED policy (N consecutive failures, back off, fall through to HTTP probes) instead of straight to a shutdown.
  3. Suppress WSL health checks for the first few seconds after startup, and while another instance still holds the default ports.
  4. Fix the relaunch so the outgoing instance has released its ports before the new one starts. The 10048 triple is a reliable detector for "a sibling is still alive."
  5. If a machine-wide shutdown is ever genuinely necessary, enumerate wsl -l -q first and tell the user which distros are about to be terminated.

Environment

  • Hydrogen 1.0.424 → 1.0.431, insiders tier, build efa297192b87a81f251d488fd5363289c4c5e52b-dirty
  • Windows 10.0.26200.9457
  • WSL 2.7.11.0, kernel 6.18.33.2-2
  • .wslconfig: networkingMode=mirrored, hostAddressLoopback=true
  • Distros registered: Ubuntu-24.04 (personal, default), docker-desktop, Adom-Workspace

2 Replies

John Lauer · 1mo ago

You're right on the cause, and thank you for the timeline. Fix is in 1.0.432 (building now; I'll add the version here when it's on the tier).

What actually happened. The update itself never touches WSL: the installer replaces the exe and re-checks Adom Bridge. The damage came from the new build's start. Every wsl.exe call goes through one wrapper, and that wrapper had a self-heal: one E_UNEXPECTED and it ran a global wsl --shutdown, then retried. The first WSL call of the new build failed that way 81 ms after boot (the installer had just force-killed the old process mid-conversation with wslservice), so the shutdown ran. Your WSL_WEDGED observation is exactly the contrast: the steady-state code needs three consecutive failures and backs off; the boot path went straight to the most destructive command on the first error.

One correction to the timeline. The 13:37:21 "Hydrogen Desktop started" line was not a second full instance. The installer runs hydrogen.exe --check-and-upgrade-ab (the Bridge version check) during POSTINSTALL; that helper run printed the start banner and exited. The 13:37:24 start was the real relaunch, and the ports it found held were the force-killed old process's sockets, not a live sibling. So there was one Hydrogen, but the log was misleading, and that's fixed too.

What 1.0.432 changes:

  1. No code path runs a global wsl --shutdown at runtime. The wrapper, the health repair ladder and the wedge ladder all use wsl --terminate Adom-Workspace (our distro only). The "safe to shut down" check that only looked for docker-desktop is gone.
  2. A management-plane error is retried with backoff (2 s, 5 s, 15 s), feeding the same consecutive-failure counter as the timeouts.
  3. For the first 60 s after boot, and for 5 minutes after an update relaunch (the updater leaves a marker: the user clicked Update on a running app, so the workspace was fine), a failure is observed only. Nothing is terminated.
  4. After that, the one remedy is the terminate, and only under the policy: 3+ consecutive failures spanning 30 s, code-server not answering over HTTP, and no terminate in the last five minutes.
  5. A relaunch whose code-server answers over HTTP makes no wsl.exe calls at launch at all (no wsl --status, no start()); the launch re-ensures run 90 s later.
  6. The --check-and-upgrade-ab helper run no longer prints a start banner.
  7. The one full wsl --shutdown left is in first-run setup, to apply a .wslconfig change (mirrored networking, the Hyper-V firewall), which a terminate cannot do. It now runs only when wsl -l -v shows no other distro Running; otherwise the config stays written, the setup log names the running distros, and nothing restarts. That's the case the README promise did not cover before; it's honest now.

The two-extension-hosts issue (#86) is separate and next.

John Lauer · 1mo ago

Shipped and verified. Insiders tier now serves 1.0.434 (1.0.432 carried the fix, 1.0.433 and 1.0.434 tightened the quiet launch; the changelog for each is on the release).

Verified on a Windows VM with a second distro registered (OtherDistro, Alpine, kept Running):

  • Updated Hydrogen 1.0.428 (the old code) to 1.0.434 through the normal self-update, with HD_TEST_WSL_FAIL=300 set so every wsl -d call for the first five minutes after boot failed exactly like a wedged service (Wsl/Service/E_UNEXPECTED).
  • 13 injected failures, 38 retries with backoff (2 s, 5 s, 15 s), spread over four minutes while the launch tasks ran.
  • No wsl --shutdown, no wsl --terminate. OtherDistro was Running throughout and after; so was Adom-Workspace.
  • Failures inside the 60 s boot window were logged as observe-only; failures after it never met the terminate policy, because the management plane itself kept answering (wsl -l -v succeeded between the failed execs, which resets the consecutive-failure streak). That's the right outcome for a service that is busy rather than dead, which is what your machine had.
  • On the two real laptops, a relaunch whose code-server answers over HTTP made no wsl.exe calls for its first 90 s (the probe now retries three times over 6 s; a single 2 s probe missed once right after an install).

Two notes:

  • The update-relaunch marker (five minutes of observe-only after an update) is written by the outgoing build, so it first applies to updates from 1.0.432 onward; an update from 1.0.431 or older gets the 60 s boot window only.
  • The full-terminate branch of the policy (3+ consecutive failures over 30 s with the management plane dead and code-server not answering) was not exercised by this injection, since it only fails execs. It is wsl --terminate Adom-Workspace, once per five minutes, and nothing else.

Closing as fixed; reopen if you ever see a distro of yours stop again.

Log in to reply.