Startup-cache save worker can outlive shared-file list owner
Summary¶
The shared startup-cache save path starts a background worker with a raw
CSharedFileList* owner pointer, posts that raw owner pointer back to the UI,
and has failure paths that can still touch owner state from the worker. Shutdown
waits only a bounded interval before abandoning the save, so late completion can
cross object lifetime boundaries.
This is a critical Beta 0.7.3 blocker because it is the same lifetime class as the background refresh owner fixes, but on the shared-files startup-cache path. A release build must not rely on a leak-or-assert convention to prevent a late worker from dereferencing deleted state.
Evidence¶
srchybrid/SharedFileList.cpp:2236allocates the worker request.srchybrid/SharedFileList.cpp:2240storespOwner = this.srchybrid/SharedFileList.cpp:3047dereferencespOwnerin the worker.srchybrid/SharedFileList.cpp:3054posts the raw owner pointer throughUM_STARTUP_CACHE_SAVE_COMPLETE.srchybrid/SharedFileList.cpp:3058handles failed UI notification by touching owner state from the worker path.srchybrid/EmuleDlg.cpp:2338waits only briefly during shutdown before abandoning the startup-cache save.srchybrid/EmuleDlg.cpp:3908trusts the raw pointer received in the UI completion message.
Execution Plan¶
- Revalidate the current startup-cache save ownership model against current
main, including normal save, shutdown save, timeout abandon, and failed UI post. - Replace the worker request's raw owner pointer with an explicitly owned save-operation state object or lifetime token.
- Ensure the worker can complete, fail, or be abandoned without dereferencing
CSharedFileListafter the owner begins destruction. - Make successful
PostMessagetransfer only the completion payload ownership needed by the UI; do not send a raw owner pointer as the authority for object lifetime. - Make failed
PostMessagea terminal cleanup path that does not call back into deleted or potentially deleting owner state from the worker thread. - Define shutdown behavior explicitly: either join the save worker before
CSharedFileListdestruction or keep the worker-owned state alive until the worker exits without requiring the owner to remain allocated. - Preserve current startup-cache file format, save timing, skip behavior after interrupted hashing, and successful startup performance behavior.
- Add targeted coverage or a deterministic seam for late save completion after shutdown abandon and for failed UI notification.
- Validate Debug and Release x64 app builds through the supported workspace entrypoints.
Acceptance Criteria¶
- No startup-cache save worker path dereferences a raw
CSharedFileList*after shutdown abandon or owner destruction begins. - UI completion does not depend on a raw owner pointer carried through
WPARAM. - Failed completion delivery performs deterministic cleanup without worker-thread UI calls or owner-state mutation after destruction.
- Shutdown remains bounded and does not leave unsafe global or owner state.
- Startup-cache save success behavior and cache compatibility remain unchanged.
- The item has commit evidence and targeted validation in this file before Beta 0.7.3.
Validation¶
- 2026-05-08: Done in app commit
bde9f16. python -m emule_workspace validate --workspace-root .passed.python -m emule_workspace build app --workspace-root . --config Debug --platform x64 --variant mainpassed; log rootworkspaces\v0.72a\state\build-logs\20260508-105211.python -m emule_workspace build app --workspace-root . --config Release --platform x64 --variant mainpassed; log rootworkspaces\v0.72a\state\build-logs\20260508-105242.- Code validation: the startup-cache save worker now carries an
owner-independent operation token and completion payload. The worker no
longer receives or posts a raw
CSharedFileList*, failed completion delivery discards persisted worker output without touching owner state, and shutdown abandon detaches the owner from the in-flight operation before destruction.