[native] Fix concurrent FastTiming event storage - #12455
Conversation
Replace the reallocating event vector with stable chunks, publish completed events safely for concurrent dumps, and fix startup-aware lock ownership. Add a CoreCLR device regression that grows and dumps fast timing events. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d40daefe-fd3f-4c2d-96d9-9c91a6b0c5c2
There was a problem hiding this comment.
Pull request overview
This PR fixes a native concurrency bug in FastTiming event storage that could corrupt the heap when timing logging is enabled under sustained multi-threaded typemap activity. It replaces the previous std::vector-backed “index into reserved capacity” approach (which could be invalidated by concurrent reserve() reallocation) with a chunked, never-moved allocation strategy and uses release/acquire publication so timing dumps can safely skip in-flight events.
Changes:
- Replaced reallocating
std::vectortiming storage with atomically-linked, never-moved event chunks; added release/acquire synchronization for “event complete” publication and dump-side filtering. - Made startup state publication atomic and fixed
StartupAwareLockso it only unlocks when it actually acquired the mutex. - Added a device integration regression test that forces timing storage to grow past the original 4,096-entry boundary and verifies a complete timing dump.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/MSBuildDeviceIntegration/Tests/FastTimingTests.cs | New CoreCLR device test stressing concurrent typemap events past the 4,096 boundary and validating dump output. |
| src/native/mono/runtime-base/startup-aware-lock.hh | Track lock ownership to avoid unlocking when the lock wasn’t acquired during startup. |
| src/native/mono/runtime-base/monodroid-state.hh | Make startup_in_progress reads/writes atomic with acquire/release ordering. |
| src/native/common/runtime-base/timing-internal.cc | Dump now skips in-flight events via acquire load of the completion flag; removes vector-realloc lock usage. |
| src/native/common/include/runtime-base/timing-internal.hh | Introduces chunked event storage, atomic enable publication, and completion-based dump filtering. |
| src/native/clr/include/runtime-base/startup-aware-lock.hh | Same lock-ownership fix as Mono header for CoreCLR runtime. |
| src/native/clr/include/runtime-base/monodroid-state.hh | Same atomic startup flag change as Mono header for CoreCLR runtime. |
|
/review |
|
✅ Android PR Reviewer completed successfully!
|
There was a problem hiding this comment.
✅ LGTM
Findings: 0 errors · 0 warnings · 1 suggestion
The chunked storage removes the invalid vector-capacity access and preserves stable event addresses; the acquire/release publication around initialization, chunk linking, completion, and startup state is coherent. The lock-ownership fix also correctly handles startup transitioning while a guard is alive. CI is green across all 45 checks.
I left one non-blocking inline suggestion to exercise dump() while timing events are still in flight, since the current regression waits for all workers to finish before requesting the dump.
Generated by Android PR Reviewer for #12455 · gpt56 · 101.6 AIC · ⌖ 8.85 AIC · ⊞ 25.7K
Comment /review to run again
Summary
Fixes #12437.
FastTimingtreated reservedstd::vectorcapacity as constructed array storage and allowed concurrent event access whilereserve()moved and freed that storage. Under sustained multi-threaded typemap activity withdebug.mono.log=timing, this could corrupt the heap and trigger Scudoinvalid chunk state when deallocatingaborts.StartupAwareLockonly unlocks mutexes it acquired;MSBuildDeviceIntegrationregression that generates concurrent native typemap events beyond the original 4,096-entry boundary and verifies a complete timing dump;Validation
MSBuildDeviceIntegrationbuild