[stable] [web] Use thread local strike caches in skwasm (#190048) - #192115
[stable] [web] Use thread local strike caches in skwasm (#190048)#192115SynSzakala wants to merge 1 commit into
Conversation
Cherry-pick of d3ac5cd onto flutter-3.47-candidate.0. Applies cleanly; no conflict resolution was needed. Fixes the multi-threaded skwasm heap corruption tracked in flutter#190039.
|
I don't have permission to apply labels — could someone from the release team add |
There was a problem hiding this comment.
Code Review
This pull request introduces a new test for concurrent text layout and rasterization under Skwasm to ensure heap stability. It also enables thread-local strike caches experimentally, refactors surface initialization to allocate the context lost callback ID on the main thread, and implements asynchronous dispatching of resource cache limit updates from the main thread to the worker thread. There are no review comments, so no feedback is provided.

Cherry-pick of #190048 (
d3ac5cdfb70971a1b28ca67240860675a6b3598c) ontoflutter-3.47-candidate.0. It applies cleanly — all four modified files are byte-identical between the fix's parent and the candidate branch, and the added test does not exist on either, so no conflict resolution was involved.Issue: #190039
Impacted Users
Anyone shipping a
flutter build web --wasmapp served cross-origin isolated — via COOP/COEP orDocument-Isolation-Policy— which is what selects multi-threaded skwasm. This hits end users of those apps, not only developers.Impact Description
A silent, unrecoverable freeze of the running app.
Multi-threaded skwasm is built with
-sWASM_WORKERSbut without-pthread, so it links the single-threaded emscripten system libraries where mutexes are no-ops. Main-thread text layout and the raster worker then share the globalSkStrikeCacheand corrupt the heap under text churn. It surfaces either asRuntimeError: memory access out of boundsfromskwasm.wasm, or as nothing at all in the console; afterwards the page never runs JS again —requestAnimationFramestops, and a core stays pinned.Field data from our production web app (Flutter 3.44.7, wasm, thousands of daily users), in case it is useful for prioritisation:
RenderParagraph.performLayout→TextPainter._createParagraph→ enginerenderer.dart→skwasm.wasm→ a busy-spin onemscripten_get_now, held for the full 7.7 s remaining in the trace. The skwasm render worker sits 100% idle beside it. The compositor keeps issuingBeginFrameat 60/s with no main frame ever committing.RuntimeError: memory access out of boundswith askwasmculprit went from 10 events across all prior releases to 111 in the two weeks after we enabled cross-origin isolation — the only change that turned multi-threaded skwasm on.skwasm.wasmfunctions, i.e. the trap and the spin are the two presentations of one defect, exactly as described in [web][skwasm] Wasm heap corruption under concurrent text layout and rasterization with multi-threaded skwasm; page then spins at 100% CPU #190039.Workaround
Yes:
forceSingleThreadedSkwasm: true, or stop serving the app cross-origin isolated. Both give up multi-threaded rendering altogether, which is the feature being paid for. We have taken the second option in production.Risk
Low. The change sets a Skia flag from a constructor in
surface.ccso each thread gets its own strike cache. There is no API or behaviour change beyond removing the shared mutable state.Test Coverage
Yes. The upstream PR adds
engine/src/flutter/lib/web_ui/test/skwasm/concurrent_text_layout_raster_test.dart, which is included in this cherry-pick.Validation Steps
build/webcross-origin isolated so skwasm picks multi-threaded mode.Before: the tab freezes within seconds (3–30 s in the reporter's runs). After: the animation keeps running.
Two notes for the reviewer:
This is not a regression introduced in 3.47. The defect has been present since multi-threaded skwasm shipped, so it sits outside the strict "regression from the previous release" wording of the cherry-pick process. I am requesting it anyway because the failure mode is a silent production freeze with no error surface for most users, the fix is already on master and in beta 3.48, and without a cherry-pick affected apps stay on the single-threaded fallback until 3.50 lands — roughly three months. Entirely happy for this to be closed if the release team would rather it ride the normal train.
Why this commit and not #191014. That follow-up swaps the experimental Skia flag for the officially supported one, and depends on a newer Skia roll than 3.47 carries, so this cherry-pick keeps the original form.