Closed general

SDK: freeze-safe desktop introspection - enumeration must say 'cannot answer' instead of returning empty during a wedged session

Colby Knox · 2mo ago ·closed by John Lauer

What happened (the exact reason a freeze watchdog missed, adom/altium-bridge#6)

During the hard desktop freezes on Colby-ROG2, desktop_enum_windows returned 0 windows and process_list came back empty or hung, exactly when the altium bridge's close watchdog needed them to detect "main window gone, process alive". Empty results read as facts, the watchdog concluded "no X2", and it dropped nothing. The freeze it was built to catch is the one condition under which its inputs lie.

Ask

  1. A documented freeze-safe mode for window enumeration: only non-messaging Win32 calls (EnumWindows, GetClassNameW, GetWindowThreadProcessId; never GetWindowText, which sends WM_GETTEXT into hung windows), so results stay truthful while a window is wedged.
  2. Replies must distinguish "empty" from "could not answer": a degraded: true / unreliable: true flag when enumeration timed out or the session is not answering, the way ab_unreachable already distinguishes transport failure. A safety consumer treats degraded data as unknown, not as zero.

Evidence: adom/altium-bridge#6 root-cause comments (2026-09-02), watchdog v2 design notes.

2 Replies

John Lauer · 2mo ago

Triaged, and I agree the empty-vs-cannot-answer distinction is the important half. Two parts:

  • Doable (queued): a degraded: true / unreliable: true flag on desktop_enum_windows / process_list when the enumeration timed out, plus making window enumeration freeze-safe by construction — EnumWindows + GetClassNameW + GetWindowThreadProcessId only, never GetWindowText (which sends WM_GETTEXT into a hung window and is exactly what lies during a freeze).
  • I want to verify the current enum path doesn't already call GetWindowText on the freeze path before I claim it; that's the audit I'll do when this comes up in the queue.

Holding for a near-term ship, not this one. Good catch that the watchdog's inputs lie under the one condition it exists to catch.

John Lauer · 2mo ago

Delivered in 2.1.9: an UNFILTERED desktop_enum_windows or desktop_list_windows returning ZERO windows now carries degraded:true plus a hint telling a watchdog to treat it as CANNOT-ANSWER, never as the-window-is-gone (a filtered empty result stays a legitimate no-match). The freeze-safety audit you asked for: the enumeration already uses only non-messaging calls - EnumWindows/GetClassNameW/GetWindowThreadProcessId, and GetWindowText on ANOTHER process's top-level window reads the caption cache without sending WM_GETTEXT, so nothing in the walk blocks on a hung window; the new hung field (IsHungAppWindow, 2.1.12) gives your watchdog the wedged-vs-busy signal directly. Closing.

John Lauer closed this · 2mo ago

Log in to reply.