Open general

tao event-loop teardown panic 'cannot move state from Destroyed' (runner.rs:371) — seen v0.1.95 and again 2026-08-03 on 0.1.304-era build

John Lauer · 7d ago

Type: Bug (extracted from #3, which is otherwise stale)

The tao Windows event-loop teardown panic is still occurring on current builds:

[PANIC] panicked at ...tao-0.35.2\src\platform_impl\windows\event_loop\runner.rs:371:25:
cannot move state from Destroyed
  • First captured 2026-06-30 on v0.1.95 during the #3 lockup exit (see that issue's log excerpt).
  • Seen again 2026-08-03 05:49 on a current dev build (0.1.304 era) in the wreckage of an interrupted migration; same runner.rs:371 signature.

Why it matters: a panic during event-loop teardown can leave zombie window state behind, which is the leading theory for #3's "HD could not relaunch until reboot". The trigger seems to be teardown while background threads (health pollers, the wake watcher's hidden message-only window thread) are still live.

Investigation plan:

  1. Reproduce with verbose teardown logging: order of window destruction vs thread shutdown at [app] Exiting.
  2. Check whether the wake-heal hidden message-only window thread (added 2026-08-02) outlives the main event loop and needs an explicit unregister/join on exit.
  3. Consider upgrading tao (changelog mentions teardown fixes after 0.35.2) or draining background emitters before exit.

3 Replies

John Lauer · 6d ago

Fresh evidence, 2026-08-04: HD died again with the same teardown signature. Log sequence:

06:01:29.169 [app] Exiting
06:01:29 [PANIC] panicked at ...tao-0.35.2\src\platform_impl\windows\event_loop\runner.rs:371:25

That's the third occurrence (2026-06-30 on v0.1.95, 2026-08-03 05:49, now 2026-08-04 06:01 on a805838-era). Pattern: a NORMAL exit ([app] Exiting) whose event-loop teardown panics. HD relaunched fine afterward this time, so the zombie-window relaunch blocker from #3 did not recur, but the panic itself is consistent.

Related finding from the same log: a separate [PANIC] at library\std\src\io\stdio.rs:1165 at 05:13:43 — the known FreeConsole stdout panic (after detach_console runs FreeConsole(), any stray print to stdout panics because the handle is invalid). Fixing that now per the existing spec (SetStdHandle to NUL after FreeConsole + a panic hook routing to hd_log); it reduces panic noise so the tao teardown signal stays clean.

John Lauer · 6d ago

Mitigation shipped + first clean exit observed (build 1c55a6d7, 2026-08-04).

Change: wake_heal::shutdown() now runs on RunEvent::Exit, BEFORE tao destroys the event loop: it drops the power-watch thread's cloned AppHandle and posts WM_QUIT to the hidden message-only window's pump. The suspect was that thread outliving teardown while holding a live AppHandle. Also added a panic hook that logs every panic with THREAD NAME + location to hd_log (the default stderr hook writes to NUL after detach_console, which is why panics were half-invisible) — the next occurrence, if any, will name its thread.

Evidence from the first ralph test (graceful /app/restart, which exercises the exact exit path):

06:01:29 [app] Exiting -> [PANIC] runner.rs:371          (reboot, OLD code)
06:50:44 [app] Exiting -> [wake-heal] shutdown: power-watch pump quit posted, app handle dropped
                          (NO panic)                      (NEW code)

Honest caveat: one clean exit is a good first sample, not statistical proof — graceful exits are rare (force-kill hd_stop never runs teardown), so this stays OPEN until several more clean exits accumulate, ideally including a Windows shutdown/reboot. The panic hook guarantees the next hit, if it comes, arrives with a thread name.

John Lauer · 6d ago

2026-08-04: several more graceful exits observed across today's ~8 build cycles (hd_stop -> relaunch) with zero runner.rs:371 panics in the log since the wake_heal::shutdown() fix. Keeping open a bit longer for soak, but the evidence is now multi-sample.

Log in to reply.