Failed refresh completion can synchronously block worker on UI thread
Summary¶
The background refresh completion path attempts async UI delivery with
PostMessage, but falls back to SendMessage when posting fails while the
window still appears valid. That lets a worker synchronously enter UI-owned
completion handling during shutdown or queue pressure.
This is a critical Beta 0.7.3 blocker because it can deadlock the application when the UI thread is blocked waiting for shutdown progress, or it can run UI-affine state transitions from an unexpected worker call stack.
Evidence¶
srchybrid/GeoLocation.cpp:59-61callsSendMessagefrom the worker after a failedPostMessageifIsWindowstill returns true.srchybrid/IPFilterUpdater.cpp:95-97has the same worker-thread synchronous fallback.- The completion handlers mutate refresh/UI state that is intended to be owned by the UI thread.
Execution Plan¶
- Revalidate every GeoLocation and IPFilter completion path that can run from a background thread.
- Remove worker-thread
SendMessagefallback for refresh completion. - Define one asynchronous ownership transfer rule: successful post transfers context ownership to the UI thread; failed post performs terminal non-UI cleanup without calling UI handlers synchronously.
- If cleanup must touch UI-owned state, route it through a safe owner-owned cancellation/join mechanism from BUG-092 rather than a blocking worker call.
- Add a focused seam for failed
PostMessage, blocked UI, and shutdown with a live worker. - Verify refresh can be retried after failed delivery and after shutdown-safe cleanup.
Acceptance Criteria¶
- No refresh worker calls
SendMessageto deliver completion to the main UI. - Failed post delivery cannot deadlock on a blocked or shutting-down UI thread.
- Completion context ownership is deterministic for post success and post failure.
- GeoLocation and IPFilter manual/automatic refresh behavior remains compatible.
- The item has commit evidence and targeted validation in this file before Beta 0.7.3.
Validation¶
- 2026-05-08: Done in app commit
2823a5c. python -m emule_workspace validate --workspace-root .passed.python -m emule_workspace build app --workspace-root . --config Release --platform x64 --variant mainpassed; log rootworkspaces\v0.72a\state\build-logs\20260508-101728.python -m emule_workspace build app --workspace-root . --config Debug --platform x64 --variant mainpassed; log rootworkspaces\v0.72a\state\build-logs\20260508-101749.- Code validation: GeoLocation and IPFilter refresh workers no longer call
SendMessagewhenPostMessagefails. Failed completion delivery clears the shared refresh state and logs the dropped completion without blocking on the UI thread.