[H2] Data race on the loaded/error maps once exec runs off-thread #20
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
indigocode/igasset-viewer-react#20
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
File:
wasm/src/observable_filestore.ccloading_state_lock_only guardsloading_igassets_/loading_igpacks_. The worker-thread lambda passed toexec_task_list_->run(...)writes the following with no lock held:loaded_igassets_(line 86)igasset_load_errors_(line 74)loaded_igpacks_(line 133)igpack_load_errors_(line 129)Meanwhile the main thread reads those same maps in
generate_event()(lines 194-219) and in theload_*entry guards (lines 38, 96). Concurrent read/write on astd::mapis undefined behavior.Impact: real UB the moment
exec_task_list_actually runs on a worker thread. Currently masked only because the thread pool is never wired (see H3), so exec tasks happen to run on the main thread. The existinggenerate_event"concurrency is hard" comment acknowledges a visibility race but not this data race.Fix: protect all shared maps under the mutex, or marshal the parsed result back to the main thread before storing (mirroring how the loading-state clear is already posted to
main_thread_task_list_).Filed by an automated AI code review (manual proof-of-concept run). Code locations reference the
various-cleanupbranch.Maps should only be copied in critical sections to avoid paying the cost of iterating through them. But yes, this should be acknowledged...
I think a better approach for this would just be to make sure that the following two actions only ever run on the main thread:
Using the
exec_task_list_to perform the actual de-seraizliation + metadata listing is fine - but a.then_consuming(...)is what should perform the actual mutations. This should include mutating the "is_loading" state - that should be set immediately, then anexec_task_list_should serialize the data and return it, so amain_thread_task_list_then_consumingcall can take the serialized data and set it on the main object.Fixed by sessamekesh/igasset-viewer-react#40