Skip to content

Commit bd8fe0d

Browse files
tjzelmeta-codesync[bot]
authored andcommitted
Skip non-owned subtrees in roundLayoutResultsToPixelGrid (#2015)
Summary: Pull Request resolved: #2015 > [!NOTE] > **This PR description is AI-generated.** Fabric runs layout on candidate trees before taking the commit mutex, and concurrent commits share every unchanged subtree, so Yoga's pixel-grid rounding pass could write rounded positions and dimensions into the same shared `yoga::Node` from two threads at once. The layout pass itself never mutates nodes it does not own (`Node::cloneChildrenIfNeeded`), but `roundLayoutResultsToPixelGrid` recursed across the ownership frontier. I made the rounding recursion skip children whose owner is not the current node, mirroring the existing owner checks in `Node::cloneChildrenIfNeeded` and `YGNodeFreeRecursive`. The skipped writes had no reader: `YogaLayoutableShadowNode::layout` copies metrics only from children with `hasNewLayout` (asserting they are owned), `hasNewLayout` is set only on nodes the pass laid out, and the shadow nodes past the frontier are sealed, so their `LayoutMetrics` could not change in that commit anyway. ## Changelog: [GENERAL] [FIXED] - Fix data race between concurrent Fabric commits in Yoga's pixel-grid rounding pass X-link: react/react-native#58144 Test Plan: ThreadSanitizer reports of the race, from react-native-reanimated's sanitizer nightly (React commit on the JS thread racing a Reanimated commit on the main thread over a shared `ParagraphShadowNode`): https://github.com/software-mansion/react-native-reanimated/actions/runs/32811464205/job/97691453444 Reviewed By: christophpurrer Differential Revision: D117688567 Pulled By: zeyap fbshipit-source-id: 3f0662aee2ce865b4a13edffd46217f349a4285d
1 parent 433d463 commit bd8fe0d

1 file changed

Lines changed: 3 additions & 0 deletions

File tree

‎yoga/algorithm/PixelGrid.cpp‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,9 @@ void roundLayoutResultsToPixelGrid(
128128
}
129129

130130
for (yoga::Node* child : node->getChildren()) {
131+
if (child->getOwner() != node) {
132+
continue;
133+
}
131134
roundLayoutResultsToPixelGrid(child, absoluteNodeLeft, absoluteNodeTop);
132135
}
133136
}

0 commit comments

Comments
 (0)